Monday, December 10, 2007

Ubuntu - is Linux finally ready for the desktop?

I've now been using Ubuntu on my laptop (a Sony VAIO - btw, the quality of the display is absolutely astounding: two years on, I'm still delighted by its brightness AND battery life) for quite a few months, and I must confess my perception of it has entirely changed.

As you can see from previous entries in this blog, I've been rather critical of Ubuntu and certain design choices - however, the more you get used to the `sudo` thing and the general approach that you don't really need to `su` to root to get stuff done, then it becomes pretty natural and, indeed, most stuff does get done.

However, the one thing that most convinces me that the folks at Ubuntu are definitely travelling down the right path, is the ease of use of the user interface (which looks way better than Windows) and also how easy has it become to add functionality.
Adding hardware has also come a long way from the times when even getting Linux to "see" a WiFi card meant compiling some drivers, editing scripts and all that nonsense that was so frustrating for all those, like myself, that saw using a Linux box as a means to an end (eg, doing development, running a web server, getting a database server up and running) as opposed to the end in itself (as it still to me seems the case with some parts of the Linux community).

Ubuntu definitely is a massive stride forward in making Linux a much more compelling proposition to the "computer savvy" professionals - developers, and IT experts - who are sick and tired of buggy, insecure and drab Windows; but at the same time don't have the time and desire to spend entire days and weeks trying to figure out why that particular kernel driver does not compile.

However, it is also important to say that Linux will really never become the OS of choice for the "great unwashed" - but this is no bad thing: trying to "dumb it down" would mean introduce technologies (such the infamous Universal PnP and suchlike) that make Windows such a security nightmare.

In other words: for those who can, Linux; for those who can't, Windows...

Saturday, October 6, 2007

Off-topic - about uselessness (and lack of testing)

Just had a taste of the "user error" disease...

Was reading a post on the Eclipse Magazine (no hyperlink here by design, you go and waste your time there, if you really want to - but use Google, I won't be complicit in this endeavour).

Early on, they managed to prove themselves less than proficient in web design with the less than friendly way of accessing the PDF of the magazine and password management; but I put that down to the typical hiccups one encounters early on in deployment / roll-out, and, anyway, managed to get past them.

Today, however, after reading a reasonably informative blog entry, I decided to post a comment - and, being the thoughtful, insightful, informed and well articulated individual that I am, I spend considerably more than the 30 seconds your usual blog-commenter does (being generally of the "well put, mate" or "total rubbish, you loser" variety) to do so.

To avoid bot-posting and spamming, I presume, they have a 'Verify' box, which is the usual kind you see pretty much everywhere these days: you are presented with a picture of letters an asked to type them up in a box and submit.

After going through the process a couple of times and getting nowhere (well, it's early Saturday morning, I thought maybe the caffeine hadn't hit the spot yet) I started to guess it might not be me after all...

I tried every combination: all lowercase, all uppercase, one letter at a time... nope - niet - nada: it just says "Not verified! . Please try again" [punctuation sic]

To make matters worse, they have Javascript that 'disables' the text box, so one cannot even copy & paste the comment for later posterity (or re-use elsewhere) - that's it, you've completely waste your time, dude, and tough luck!

Now, bearing in mind that this is a website dedicated to Eclipse users (so one would assume, somewhat versed in the use of Java and coding in general) that they would be familiar with the concept of 'testing' - but, alas, apparently not.

PS - feel free to post comments here: it's safe, we don't verify and, if we do, it does work.
How do I know? well, I do have comments on my blog (unlike Eclipse Magazine) :-p

Sunday, September 23, 2007

GWT rocks!

I have recently been experimenting with the Google Web Toolkit, and it really rocks!

In less than a couple of days' work I was able to create a full featured demo app, with toolbars, menus, help pop-up's and other bits and pieces - essentially a true Rich Internet Application (RIA).

A few points that I think are worth for the novices, like me:

  • if you don't know CSS, learn it fast - it is an inseparable component of GWT and enables one to do all the formatting, positioning and styling that would be virtually impossible from GWT alone;
  • use Eclipse for the development / code editing - there is an excellent integration from within GWT, although, in my view, it could be better;
  • it is worth considering the use of ant for all the build, deploy and run tasks - GWT applicationCreator will generate some simple scripts to do that for you, but using ant gives much greater control and flexibility to the whole process; especially if you are deploying to an instance of Tomcat that is not the one that comes packaged with GWT (which is the most likely situation in a real-life environment);
I am using "GWT in Action" (R. Hanson, A. Tracy) which, if a bit verbose and too light on details, seems like a good starting point - definitely better anyway of the very limited amount of information one finds on Google Code.

One thing I do not understand is Google's choice of their somewhat weird choice of not using Javadoc to document GWT classes - quite apart from the fact that makes it harder for us all to figure out where things are (for example, the lack of an 'All Classes' options, leaves us wandering around packages to find out a class' description), it also turns out that some methods's descriptions are missing, whilst others are actually not correct.

But those are very minor gripes - the speed at which one can craft a fully-featured RIA, even for someone who has very limited knowledge of Javascript, is a priceless feat: thanks, Google!


Saturday, May 19, 2007

Ubuntu fixed (sort of )

Ok, so I decided that (a) a laptop without the "Suspend" / "Hibernate" was only marginally more useful than a door-stopper and (b) that I could do it, if I really wanted.

I'd also discovered that, out of the box, Ubuntu would not support an external monitor - which was a bit unsettling, as I was due to give a presentation the next day (to no less than Google folks!) and was planning to do so from the laptop.

Fire up Google, search for "Ubuntu dual head" and up pops HowTo: Dual Monitors a very well written article, with plenty of detail.

It turns out that the source of so much misery were the missing nVidia drivers - installing them following this How-To was a piece of cake and that also had the nice side effect to enable the external monitor.

One thing that still troubles me is that I have been thus far unable to find a way to make Ubuntu recognise the special function keys (you know, the ones that allow you to change brightness, volume, etc. and, critically, switch the LCD/External monitor) so to have the external monitor to work, one has to re-start (Ctrl-Alt-Backspace) the X server.

I have so far been unable to make Twinview work and I am using Xinerama instead - although, apparently, Twinview was designed exactly for nVidia cards, my (admittedly, feeble) attempts to make it work have miserably failed: I decided that life is too short and can live quite happily with Xinerama.

A more general consideration is that it took me the best part of a Sunday afternoon and several trial and errors (for God's sake, whatever you do, make a backup of xorg.conf at each and every step - trust me, you'll need them!) - to achieve something that Windows gives you straight out of the box (and, to be fair, most Linux distros): I am still quite unsure whether choosing Ubuntu was as clever as I thought it was.

On balance, I'd recommend Suse Linux: I have v. 10 installed on my other laptop (a much older one that I use as a staging server for my Tomcat Java apps) and it is much easier to manage, configure and, generally, use.

Also RedHat's Fedora Core felt a lot easier to use, although much less "flashy" than Ubuntu.
I used to run FC4 on yet another laptop as a development/testing box - had all sorts of servers and tools running on that one: despite years of abuse, I never really managed to crash it: the same, sadly, can't be said of my Windows dev PC, that recently enjoys crashing on me rather spectatularly): I can only assume that FC6 is even better (and FC7 is about to be released).

Now, if only I could get the little battery guy to see some sense ...
(although, I must admit it's got its amusement value: yesterday warned me of 5 remaining minutes of power as soon as I unplugged the power cable, after an entire day charging)

Monday, May 7, 2007

Ubuntu, NetBeans and Sun's Application Server (Glassfish)

I have recently read that Sun and the folks behind the Ubuntu Linux distro are getting some sort of strategic partnership and closer cooperation.

Well, not one day too soon, say I.

For the poor souls like myself that have been struggling to get Ubuntu to be a bit more co-operative and let the Sun App Server (SJAS) do its stuff, it's been quite trying.

For a start, although I may intellectually agree with Ubuntu's desire not to let root roam free and cause havoc, that is hardly helpful when people like myself spend 90% of their time on a Linux box doing exactly the kind of stuff root is supposed to be doing (set-up the server, install and remove stuff, create/delete/fiddle endlessly with configuration options, firewall, user access rights, and other highly amusing stuff...)

The novelty of having to type endlessly sudo/gksudo sort of wears thing after the 900th time you've done it in two hours....

However, having decided to endure it for a while and see whether that would lead to a better world, I made a fundamental mistake...

I installed NetBeans, SJAS and MySQL (server) as root

Now, isn't this what you are supposed to do?
As root, you install the applications, and then create 'safe zones' for the users (or, equivalently, assign rights to mysql users) so that they won't mess up with the installation and other users' data.

Well, if you do that, NetBeans, SJAS and MySQL won't love each other, in fact they'll loathe each other, the world and, most critically, you!

For example, SJAS will start (well, sort of), but NetBeans won't be able to figure it and will sit there endlessly until it times out (and, by the way, whoever set the timeout value must have a Buddhist monk, as it takes forever to do so!)

MySQL for its part will install and start well enough, but then won't let you create new databases and/or new tables on existing ones - unless, that is, you go manually in /var/lib/mysql and change (chown) ownership to the user.
Something I don't particularly like, but let's face it, who else is going to fiddle with that dir?
Hackers? never!

So there you have it: if you want NB, SJAS and mysql to happily talk to each other, the only solution I have found is to create a /development folder in which to install them - whose ownership is for the 'users' group, and install them both as one of the 'users'
As per mysql, it would seem that by keeping mysql:mysql as the user:group for /var/lib/mysql location makes it all work.

However, to be totally, honest, I'm rather sick and tired of Ubuntu: I have installed it on a Sony Vaio laptop (not exactly a rare or exotic choice of hardware) and almost nothing seems to work as intended:

  • I can't get it to hibernate / standby, as the display won't come back;
  • I can't get it to see the "special function" keys (brightness, function keys, external display, etc.);
  • the battery meter is a confused little guy (how for a battery meter that tells you that there is 63% left - correctly - and then goes on to state that "only 5 minutes " are left?);
  • sometimes, when the screen saver comes on, the display colours palette gets entirely messed up and the only way to get back a sembiance of normality is to log off and log back in (effectively, restarting the X server).
Apparently, you can update and rebuild the kernel to make it all work - but, as self-inflicted pain goes, I prefer a walk to the dungeon downtown to get whipped...

I mean, none of this is reason enough to go back to Microsoft Windows (one thing is not being able to hibernate, another is having to reboot every couple of hours or so, and having your server wide open to anyone who's bothering to hack into it) - so I've ordered Sun Solaris 10, one would hope that its integration with Sun's Application Server and NetBeans is slightly better.

Watch this space...

Dynamic Pages adds AJAX to your JSF pages

I was going through the "Adding Ajax to JavaServer Faces Technology With Dynamic Faces" tutorial, and it occurred to me that it would have been a much more AJAXy solution to have the check on the existence of the User ID to occur when the user moved to the next field (without the need to click on a button - which is so Web 1.0 !)

That is easily done, by removing the "Check for user ID availability" button altogether, and adding the Dynamic Faces action on the 'onblur' method for the user ID text field:


                
<!-- Dynamic Faces usage follows: -->
<h:inputText required="true" id="userid" autocomplete="off"
binding="#{Register_Backing.userid}"
valueChangeListener="#{Register_Backing.userIdChanged}"
onblur="DynaFaces.fireAjaxTransaction(this, {
execute: 'userid',
render: 'userIDAvailableMessage',
immediate: true});
return true;" />
<h:message for="userid" errorClass="ValidateError"/>
<br />
<!-- this is the element rendered by the AJAX request -->
<h:outputText style="{color: red}" id="userIDAvailableMessage"
value="#{requestScope.userIDAvailableMessage}" />
<br />


The userIdChanged method in the Register.java class simply calls the original checkUserIDAvailable method:

public void userIdChanged(ValueChangeEvent e) {
ActionEvent aev = new ActionEvent(e.getComponent());
checkUserIDAvailable(aev);
}

It is also worth noting that the installation instructions at the beginning of the article are particularly uninformative - in fact, it is NOT necessary to download and install the Sun Developer Web Pack (I found the idea particularly frightening, as apart from the installation process being particularly cumbersome, it also seemed like the shortest path to messing up my carefully crafted NetBeans / Tomcat / Sun App Server (GlassFish) settings).

In fact, jsf-extensions (Dynamic Faces) is likely to already be in your NetBeans installation (if you have installed the Visual Web component) or, equally simply, can be installed by downloading it from the Dynamic Faces Project page.

Sunday, May 6, 2007

J2ME Multi-Threading and HTTP (Part 2)

In part 1 of this series, I have explained how to implement a LongRunningTask.
All the magic, however is done in the ControllerThread class, which takes care of executing the task, keeping tabs on it and, eventually, terminating it if it overstays its welcome.

Before getting on to ControllerThread, it is worth, however, to briefly review the Observer interface that will have to be implemented by the calling class.

We need an Observer here mostly for three reasons:

  • because of the asynchronous nature of the call, we need a way to communicate back when we are done with our task (if you look back at the last snippet of code in Part 1, you'll notice that startRecording() returns immediately: however the recording itself will last a few seconds, until either the user stops it, or the ControllerThread "expires" - in this case, after 10 seconds at most);
  • we may also want to be notified of progress (eg, by showing a "progress bar" to the user);
  • most importantly, we need to be notified when the task failed (that is, a TaskException was thrown).

Bear in mind that we cannot "wrap" the call to Thread.start() with a try/catch block, as no exception will ever be thrown by this code - catching the TaskException is a job for the ControllerThread (and the reason why LongRunningTask does not implement Runnable).

The Observer interface is defined as follows:


public interface Observer {
  /**
   * A simple logging ability, this has to be implemented in a
   * thread-safe manner, eg wrapping the logging with synchronized blocks
   *
   * @param msg a simple logging message
   */
  public void addMsg(String msg);

  /**
   * callback for signaling progress of time-consuming process, provides
   * an opportunity to either allow stopping the background operation or
   * update an UI element providing visual indication that the application
   * is not 'stuck'
   */
  public void idle();

  /** time-consuming operation complete, results, if any, are available */
  public void complete();

  /** acknowledgement of interruption, optional */
  public void interrupted();

  /**
   * This is called by the LongRunningTask to signal progress, could
   * be used to update some UI element (eg a progress bar)
   *
   * @param progress a value (meaningful to the application's semantics)
   *      that indicates progress.  Most typically, a value between 0
   *      and 100, to indicate percentage progress towards completion.
   */
   public void announceProgress(int progress);

  /** Called when the task fails */
  public void fail(TaskException tex);
}

Once a LongRunningTask is started, it will either complete() or fail(): these methods will be called by ControllerThread (not LongRunningTask); the latter will either complete the execute() method normally, or throw a TaskException to indicate failure.

ControllerThread is a pretty long class: the full source code can be found here, only snippets of code will be shown in the following.


public ControllerThread(LongRunningTask task, long waitInterval,
long timeout, Observer observer)

The constructor takes a reference to the task to execute, an (optional) reference to an Observer and two numeric values that indicate, respectively, how often it should check on progress and how long the task is given to complete its work.

ControllerThread does implement Runnable - it is executed in its very own thread and creates (and executes) in turn another thread: as I mentioned in the first part of this article, to execute a background thread, you need two threads, just one won't do!

public void run() {
  long start = System.currentTimeMillis();
  long elapsed;
  Thread t = new Thread(new ControllerRunnable());
  t.start();
  while (!task.isDone() && !task.isStopped() && !failed) {
    wait_state = THREAD_STATE_WAIT;
    elapsed = System.currentTimeMillis()-start;
    if (elapsed > totalTimeout){
      task.cancel();
      wait_state = THREAD_STATE_EXPIRED;
      getObserver().interrupted();
      return;
    }
    synchronized (lock) {
      try {
        // double-check to avoid race conditions
        if (!task.isDone() && !task.isStopped())
          lock.wait(waitTimeout);
      } catch (InterruptedException ex) {
        failed = true;
        failureMessage = "ControllerThread interrupted";
        t.interrupt();
        getObserver().interrupted();
        return;
      }
    }
  } // while
}

All the magic is done in the internal class ControllerRunnable that implements Runnable itself and inside its run() method actually executes the LongRunningTask, wrapped in a try/catch block to catch failures.
private class ControllerRunnable implements Runnable {

  public void run() {
    if(task == null) {
      failureMessage = "No task to execute";
      failed = true;
      getObserver().fail(new TaskException("No task to execute"));
      return;
    }
    try {
      task.execute(getObserver());
      synchronized (lock) {
        lock.notify();
      }
      getObserver().complete();
    } catch(TaskException ex) {
      failureMessage = new String(ex.getMessage());
      failed = true;
      getObserver().fail(ex);
    }
  }
}

As you can see, it is ControllerRunnable.run() that calls the Observer's complete() or fail() methods, and ensures that:
  • one and only one of those methods will be called;
  • that they will be called at most once.

This is critically important in the very frequent case of real-life applications that have multiple tasks that may be executing at any one time (and, possibly, even concurrently) and hence are likely to have state variables to control what's going on: in this case, calling twice complete() is almost as bad as not calling it at all.

Note also the wait/notify mechanism (lock is simply an Object, private to ControllerThread, used to synchronize the two threads) to signal the controlling thread that we are done and that is no longer necessary to wait. If the notification fails to arrive within the timeout value set when creating the controller thread, the task will be terminated (see ControllerThread.run()).

From an application developer's point of view, however, all of the above can be treated as "magic."

All one has to do to use this framework is:
  • write a time-consuming task as a single execute() method;
  • wrap the time-consuming task in a class that implements LongRunningTask (bearing in mind that most of its methods are optional - only execute() is, rather obviously, mandatory);
  • implement Observer in the calling class (most likely, a Controller class in an MVC pattern) - this will also include, probably, adding a "Stop" command to the UI as well as some sort of progress indicator (eg, a Gauge);
  • wrap the call to the time-consuming task in the following code:


public class Multimedia implements Observer {

  // Observer interface implementation omitted here
  // ref. source code & Part II of this article

  public void startRecording() {
    task = new RecordTask();
    thread = new ControllerThread(task, 1000L, 10000L, this);
    new Thread(thread).start();
  }

  // Other stuff goes here...
}


Update: I have uploaded the source code to BitBucket, you can easily download it using Mercurial (see here for an intro) by simply using:
https://marco@bitbucket.org/marco/j2me_threads

Sunday, April 29, 2007

HTTP POST from a J2ME midlet

NOTE - this blog has now moved to codetrips.com
It is highly recommended that you read the original post there.

-------------

Although there are several examples and tutorials about how to connect to an HTTP server from a J2ME Midlet, I found that they all seem to concentrate a lot on the details of a GET and the POST is always assumed as an "exercise to the reader."

Now, although it is indeed rather straightforward to work out how to send POST requests to a server, I found (the hard way) that there are certain "minor details" that are best not forgotten.

I have thus decided to post here a brief example of how to send a request to a server, using a form-encoded body, so that either a JSP or a servlet can retriever the parameters, but one can benefit from the many advantages of POSTing, as oppposed to GETting.

The source code follows, I believe it is reasonably self-explanatory and comments should guide even the most novice reader through, but please do let me know if you feel that this is still too cryptic:


private void OpenConnection(String server) 
throws java.io.IOException {
// TODO: the actual "resource" part of the URL (/test in this case)
// should be either passed as a parameter or obtained at application
// level (maybe even set up at runtime).
// To test this code, I have written the simple Servlet below, however
// this would also work with a JSP page that echoes back the contents
// in text/plain format for the midlet to display.
//
  String url = "http://"+server+"/test"; 
  byte[] data = null;
  InputStream istrm = null;

  HttpConnection http = (HttpConnection)Connector.open(url);
  http.setRequestMethod(HttpConnection.POST);

  // This allows a JSP page to process the parameters correctly
  // This format (or content type) is the same as when forms are
  // submitted from a web page.
  http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

  // You may want to indicate to the server side (eg servlet) that 
  // this request is coming from a specific application.  This would
  // allow generation of appropriate format for the content.
  http.setRequestProperty("User-Agent", "HttpMidlet/0.2");

  // You can send any custom property as part of the HTTP header
  // This would matter for the "infrastructure" code, as opposed
  // to "body parameters" that would matter to the application
  // (eg, user=marco)
  http.setRequestProperty("Custom-Property", 
      "MyCustomProperty/1.0; AnotherProperty/debug_0.1");

  // You MUST create the body of the post BEFORE actually opening
  // the stream, otherwise you won't be able to set the length of
  // the request (see next step).
  // In this example, I am sending coordinates to a mapping server
  String msg = "x="+location.getX()+"&y="+location.getY();

  // THIS is important! without it a JSP won't process the POST data
  // it would also appear that CASE MATTERS (using "Content-Length" -note 
  // the capital 'L'- caused my servlet to return -1 from the 
  //    HttpServletRequest.getContentLenght() method
  http.setRequestProperty("Content-length", ""+msg.getBytes().length);

  // After this point, any call to http.setRequestProperty() will
  // cause an IOException
  OutputStream out = http.openOutputStream();
  out.write(msg.getBytes());
  out.flush();

  if (http.getResponseCode() == HttpConnection.HTTP_OK) {
    int len = (int)http.getLength();
    istrm = http.openInputStream();
    if (istrm == null) {
      log("Cannot open stream - aborting");
      throw new IOException("Cannot open HTTP InputStream, aborting");
    }
    if (len != -1) {
      data = new byte[len];
      int bytesRead = istrm.read(data);
      addProgressMsg("Read "+bytesRead+" bytes");
    } else {
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
      int ch;
      int count = 0;

      // This is obviously not particularly efficient
      // You may want to use a byte[] buffer to read bytes in chunks
      while ((ch = istrm.read()) != -1) {
        bo.write(ch);
        count++;
      }
      data = bo.toByteArray();
      bo.close();
      addProgressMsg("Read "+count+" bytes");
    }
    response = new String(data);
    addProgressMsg("finished");
  } else {
    log("Response: "+http.getResponseCode()+", "+http.getResponseMessage());
    response = null;
    addProgressMsg("failed: "+http.getResponseMessage());
  }
  // This is critical, unless you close the HTTP connection, the application
  // will either be consuming needlessly resources or, even worse, sending
  // 'keep-alive' data, causing your user to foot unwanted bills!
  http.close();
}


To test this code, all that is required is a simple Serlvet that runs, for example, in an Apache Tomcat JSP container:
public class ConnectivityDiag extends HttpServlet {

  private static final String REVISION = "0.0.04";
  private static Logger log;

  public ConnectivityDiag() {
    if (log == null) {
      log = Logger.getLogger(getClass().getName());
      BasicConfigurator.configure();
    }
  }

  public void doGet(HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
    doProcessRequest(req, res);
  }

  public void doPost(HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
    doProcessRequest(req, res);
  }

  public void doProcessRequest(HttpServletRequest req, HttpServletResponse res) {
    BufferedReader reader = null;
    Writer writer = null;

    try {
      // Note this call seems to be case-sensitive
      // if the midlet does not set exactly "Content-length"
      // as the property, -1 will be returned
      int len = req.getContentLength();
      String contentType = req.getContentType();
      log.debug("Len: " + len);
      log.debug("Type: "+contentType);

      int bytesRead = 0;
      String remoteHost = req.getRemoteHost();
      String userAgent = req.getHeader("user-agent");
      log.info("Accessed at " + (new Date()) + " from " + remoteHost
          + ", using " + userAgent);

      // This simply echoes the parameters back to the client.
      // A JSP would use these in a  tag
      // and the ${param} macro.
      ArrayList strings = new ArrayList();
      Enumeration e = req.getParameterNames();
      while (e.hasMoreElements()) {
        String param = (String)e.nextElement();
        String value = (String)req.getParameter(param);
        strings.add(param+" = "+value);
      }
      res.setContentType("text/plain");

      // This is a custom property, that the remote client 
      // could query
      res.setHeader("Sent-at", new Date().toString());

      writer = res.getWriter();
      writer.write("Diagnostic servlet - Rev. "+REVISION);
      writer.write("\nBytes received: " + len);
      writer.write("\nFrom: " + remoteHost);
      writer.write("\nUsing: " + userAgent);
      writer.write("\n=== Parameters ===\n");
      for(String s:strings) {
        writer.write(s);
        writer.write('\n');
      }
      writer.write("=== Parameters end here ===\n");
      writer.flush();

    } catch (IOException e) {
      log.error(e.getMessage());
    } finally {
      try {
        if (reader != null)
          reader.close();
        if (writer != null)
          writer.close();
      } catch (IOException ex) {
        log.error(ex.getMessage());
      }
    }
  }
}

Saturday, April 28, 2007

Microsoft Cabs

Apparently:

If you hail a black cab you might be getting your ride to work for free, courtesy of Bill Gates. OK, it’s not as simple as that - nothing ever is.

But if you happen to find a cab between 7.30 and 9.30 a.m. in London zone one or two with a Microsoft logo – you’re in the money. Apparently this is all done to help workers have a better day in the office as the Tube gets less and less bearable in summer.

(Rainier PR Briefs of April 27, 2007)

A thought occurred to me: wouldn't we all have a (much) better day at the office, if Microsoft were to put a tiny little more effort in releasing products with less bugs? and waste less of their (and our) time on pointless marketing initiatives?

And maybe a half-decent Operating System that does not crash on you for unknown reasons, that is secure, that does not require re-booting every time a ill-designed application crashes?

Ah, I hear you saying, but such an OS already exists: it's called Linux!


Tuesday, April 10, 2007

J2ME Multi-Threading and HTTP

Update: This is Part I of a two-part series about multi-threading in the J2ME environment, Part II can be found here.
I have uploaded the source code to BitBucket, you can easily download it using Mercurial (see here for an intro) by simply using:
https://marco@bitbucket.org/marco/j2me_threads
...

In my experience, one of the most difficult things to achieve in software (and even
more so in "limited" environments, such as J2ME) is to harness certain "long-running tasks" so that:



  • they have enough time to complete their task, yet they do not
    hog the system so as to make it unresponsive to users (who would
    then have the impression the application is 'hung');
  • it is easy to both check on whether they are still running or are, indeed, 'hung';
  • it is relatively straightforward to set a timeout, expired which, they will be, rather uncerimoniously aborted;
  • it is relatively straightforward to enable a 'Cancel' option for the user to press if they get bored before the timeout expires.

The hortodox answer to this has been (and quite rightly so) to have the long running task run in a separate thread from the main (GUI) thread, with a boolean variable to control execution.

Something like this:

public class MyLongTask implements Runnable {

  private volatile boolean stopped = false;
    public void stop() {
    stopped = true;
  }

   public void run() {
     boolean finished = false;
     // do some setup here
     // ...

     while (!stopped && !finished) {
       doAChunkOfWork();
       finished = amIDone();
     }
   }
}

or something similar to that.
The controlling thread (typically the one that runs the GUI too, which has probably a "Cancel" button hooked to a cancelTask() method) looks something like this:

public class Controller {
  private MyFrameView theView;
  private MyLongTask task = null;

  public Controller(MyFrameView theView) {
    this.theView = theView;
  }

  // various other stuff...

  public void doStartTimeConsumingTask() {
    task = new MyLongTask();
    new Thread(task).start();
  }

  public void doCancel() {
    if(task != null)
      if (! task.isFinished())
        task.stop();
  }

  // other Controller "stuff"

}


This is, in fact, what the good folks at Sun in the NetBeans team have essentially done, by defining the CancellableTask interface and a generic SimpleCancellableTask class (although, the latter, quite sadly has not implemented... the cancel() method!).

This was mostly done to supporting NetBeans' WaitScreen component and, even then, I found it not terribly compelling. (see Lukas Hasik's blog here).

Initially, when confronted with the problem, I simply extended SimpleCancellableTask, and used the stopped/stop() mechanism to enable the cancel() mechanism - that enabled my application to stop a long running task that had overstayed its welcome; however, at the price of having to throw a RuntimeException to communicate back to the WaitScreen that it was done, but had not finished its task.

So far, so good.

However, there is still no easy way to set a timeout task, nor we have implemented any mechanism to let MyLongTask tell Controller they're done (let alone let the latter communicate back to the the View, which, most likely, will display something to the user to tell her we're done).

The latter problem is easily solved with the Observer pattern (see my other post - to be published later): this can be implemented by either the view or the controller - my preference has always been for the Controller to act as the observer (again, I seem to be in broad agreement with most practitioners - those times when, for expediency, I have implemented that in the View, I have always come to regret it... Thank God for Refactoring!).

Setting a timeout and generally keeping tabs on the long-running task, in fact, requires that one uses an additional, controlling thread.
In other words, to properly manage a time consuming task, you need two additional threads - just one won't do.

I decided then that a more general solution was needed, one that would allow an easy, programmatic way of controlling a long running task and was, ideally, also "pre-wired" with an observer.

My approach uses a ControllerThread, a LongRunningTask interface and an Observer interface.

The code can be downloaded here, please note that this is written specifically for 'microedition' environments(J2ME), hence no generics or any other Java 5 niceties are used.

The LongRunningTask interface is reviewed below, the ControllerThread will be analysed in Part 2 of this article.

LongRunningTask is a relatively straightforward interface, that defines a couple of 'check-me' methods (isDone() and isStopped()) the obvious cancel() one and an optional progress() method, that returns a percentage value to completion (the actual semantic of the value returned by progress(), is worth noting, is entirely application-dependent, although I like to use it as a % value, to update, for example, a Gauge UI indicator).

The 'quirk' here is that LongRunningTask does not extend Runnable: the reason for this will be clearer when we'll come to look at ControllerThread (that does implement Runnable). All the work is done in execute() that throws a TaskException (unlike run() in Runnable) and can thus indicate abnormal termination to a 'wrapper' class.

To use the framework, one simply implements LongRunningTask for a class with a time-consuming method, and checks regularly on a boolean variable that may be set by cancel() (or any other sensible way to communicate to a running thread that it's time to quit it, enough is enough).
public class RecordTask implements LongRunningTask {

  private boolean stopped;
  private boolean done;
  private int progressIndicator;

  private byte[] audioData;

  /** Creates a new instance of RecordTask */
  public RecordTask() {
  }

  public boolean cancel() {
    stopped = true;
    return true;
  }

  public boolean isStopped() {
    return stopped;
  }

  public boolean isDone() {
    return done;
  }

  public int progress() {
    return progressIndicator;
  }

  /**
   * This is where all the time-consuming work is done:
   * here we record a speech segment, long at most maxDuration
   * or until the user presses a "Stop" command (that in turn will cause
   * the controller to call cancel()
   *
   * @param observer the observing class
   */
  public void execute(Observer observer) throws TaskException {
    observer.addMsg("Record started");
    try {
      done = false;
      stopped = false;
      Player player = Manager.createPlayer(getAudioMimetype());
      if (player != null) {
        player.realize();
        RecordControl rc = (RecordControl) player.getControl("RecordControl");
        if (rc != null) {
          observer.addMsg("RecordControl: OK");
        } else {
          observer.addMsg("No RecordControl, exiting");
          return;
        }

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        rc.setRecordStream(bos);
        rc.startRecord();
        player.prefetch();
        player.start();

        long start = System.currentTimeMillis();
        while (!isStopped() && ((System.currentTimeMillis()-start) < getMaxDuration())) { 
          calcProgress(start);
          observer.announceProgress(progress());
        }
        rc.commit();
        player.close();
        audioData = bos.toByteArray();
        observer.announceProgress(100);
      }
      done = true;
    } catch (Exception ex) {
      observer.addMsg("Recorder exception: "+ex.getMessage());
      // The following is necessary to communicate back to ControllerThread
      // that an error condition was encountered
      throw new TaskException("Recorder exception: "+ex.getMessage());
    }
  }
  // Other utility methods follow....
}


Then, an instance of this class is passed, at construction, to a newly created instance of ControllerThread:
public class Multimedia implements Observer {

// Observer interface implementation omitted here
// ref. source code & Part II of this article

public void startRecording() {
  task = new RecordTask();
  thread = new ControllerThread(task, 1000L, 10000L, this);
  new Thread(thread).start();
}

// Other stuff goes here...
}


And that's pretty much about it: with the code above, we have created and started a new task which we'll check every second (1000L msec) and will allow at most 10 sec (10000L msec) to complete.
All the magic is done in ControllerThread - explained in part 2 of this series.

Tuesday, March 27, 2007

Going International


I find rather amusing that, despite English not being my first language, I never really bothered looking into how to write software (and, in particular GUI components) using anything else than (tortured) English.

Entirely by chance, yesterday I eventually looked into "Resource Bundles" that allow one to easily create an application in Java that will be, one would hope, easier to distribute in several languages.

Here's how it works.

The basis of all this are "resource bundles" - in practice, simple properties files that have a list of mnemonics (eg, "s1", "file_not_found", "ad2234", etc.) and the corresponding string as the value ("Please don't click here", "File not found", etc.)
Let's call this file `messages.properties`

So far, so good.
The real beauty comes into play, in the simplicity of using a different Locale (eg, Italian) for a particular distribution. To achieve that, one creates an identical file (called `messages_it.properties`) with the same keys, and their equivalent values in the destination language ("Per favore, non cliccare qui", "File non trovato", "Buonanotte ai suonatori", etc. etc.)

In the application code, the selection as to which one to load is delegated to

ResourceBundle.getBundle("bundles.messages", new Locale(lang));

where `lang` could be `null` (in which cause the user's default locale would be used) or it could be a String with values such as `it`, `en_US`, `de_CH` and so on.

Please note that the .properties files MUST be saved inside a package within the classpath (I prefer to use something along the lines of `bundles` (as in the example above) but anything would do, really.

(so calling ResourceBundle.getBundle("com.ibw.utils.complex.package.name.if.you.wish.messages", "ru"); would work just as well - just make sure you save the properties files in the appropriate folder - and, yes. please do consult a mental health professional).

Were this not simple enough, NetBeans (don't you just love the Sun folks and the NetBeans community in general? thanks for being here folks!) makes it even easier.

Just right-click on a project and choose "Create new package" (if a suitable one isn't there yet) and then right-click on the package and choose "New/Properties file..." choose whathever name takes your fancy (eg, `system_messages`) and bob's your uncle the default resource bundle is created and opened in the editor.

The default properties file will look something like (example taken from the Javadoc API, here):

s1=The disk \"{1}\" contains {0}.
s3=My disk
s4=no files
s5=one file
s6={0,number} files
s7=3 Mar 1996

Then, let's say you want to create the Italian version, it's simply a matter of right-clicking on the properties file and selecting "Add Locale," either choosing from the list a 'pre-cooked' language/country/variant or choosing freely from the drop-down lists.

You will, of course, have to supply the Italian version of the various messages, like in:

s1=Il disco \"{1}\" contiene {0}.
s3=Il mio disco
s4=nessun file
s5=un file
s6={0,number} files
s7=3 Marzo 1996

but then choosing which locale to use in your code will be as simple as:

public static void main(String[] args) {

String lang = null;
PropertyResourceBundle messages;
if (args.length > 0) {
lang = args[0];
messages = (PropertyResourceBundle)
ResourceBundle.getBundle
("bundles.messages", new Locale(lang));
} else
messages = (PropertyResourceBundle)

ResourceBundle.getBundle("bundles.messages");
String s1 = messages.getString("s1");

System.out.println("Given language: "+
(lang==null? "default":lang)+
"\tThe message is: "+s1);
}

Depending on how you run it (say, java MyApp it) the output will be in the chosen locale.

Now, say you want to use this in a practical GUI (Swing) app, you face the problem that the text label on, say, a button, is defined in the generated code and NetBeans won't let you edit it.

In fact, it is quite easy to use a Resource Bundle here, and in fact, it's actually easier than hand-crafting the code.

After creating a button the usual way in the Swing layout editor, look at the "Properties" pane (it is usually bottom right): there is a 'text' property (in bold) that you can customise (by typing directly in the edit control): if you instead click on the "..." button on the right, it will open a dialog window, where you can select from a drop-down list, "Resource Bundle".


At this stage it's just a matter of entering the fully qualified name of the bundle (bundles.messages) and choosing whichever key identifies the text you want to appear on the button (eg, `s3').

You will see in the "Replace string:" box (which you can't directly edit) the code that NetBeans will generate to replace the text in the button and, when deployed in a locale for which you have provided a bundle, it will use as the text the appropriate entry.

Piece of cake, uh?

Monday, March 26, 2007

Java Code Trips & Tips


The idea behind this blog is more to use it for my own personal benefit, as a means of annotating big and small discoveries in my use of Java, Linux, Tomcat and MySQL that would be easy to access from anywhere, anytime. It does beat post-it's big time, and it also adds the benefit that others might, eventually, contribute with intelligent insights. But, let's face it, there must be thousands of Java-related blogs, and even just keeping track of all of them (which I hope to be able to do for some, by adding links - so, please if you do know of good ones, please do let me know) so I don't expect massive traffic here. (in fact, if you do know of some simple means of measuring the 'page impressions' on this blog, that would be grand). Comments always appreciated and encouraged, but please do ensure you leave a means of being contacted, if possible at all, otherwise intelligent discussion will not be had...