Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

05 February, 2007

Don't Over-Work Your Swing Thread

I know at least three different teams that I've worked with in the past that screw up Swing thread handling. Frankly, they should all know better. People, there is no such thing as a single-threaded Java Swing application. Fortunately, the Java 6 standard library is getting an addition that should help developers with this problem: the SwingWorker API.

One common mistake of desktop application programmers is misusing the Swing event dispatch thread (EDT). They either unknowingly access user interface (UI) components from non-UI threads or simply disregard the consequences. The result is that applications become unresponsive or sluggish because they perform long-running tasks on the EDT instead of on separate worker threads. Long-running computations or input/output (I/O) bound tasks should never run on the Swing EDT. Finding problematic code may not always be simple, but the Java Platform, Standard Edition 6 (Java SE 6) makes it easier to fix such code by providing the javax.swing.SwingWorker class.

One of the reasons I tend to prefer SWT over Swing is that it seems to be better about throwing nasty exceptions when you try and step over the UI thread. Neither is perfect, but I tend to get more exceptions when I do stupid stuff in SWT. If I do something stupid in Swing, I get a grey box and a frozen UI.

11 January, 2007

Fun with HTTP

The HTTP protocol specification can be a bit daunting and I was curious what the data in a POST request looks like. So, just for fun, I dumped out a little Ruby WEBrick servlet program that returns the contents of any HTTP GET or POST requests it receives. It looks like this:

#!/usr/bin/env ruby
#
#  Created by Toby Tripp on 2007-01-11.

require 'webrick'

class PostDumper <
  WEBrick::HTTPServlet::AbstractServlet
  
  # Reload file for each request, instantly
  # updating the server with code changes 
  # without needing a restart.
  #
  def PostDumper.get_instance( config, *options )
    load __FILE__
    PostDumper.new config, *options
  end
  
  def do_GET( request, response )
    response.status = 200
    response['Content-Type'] = "text/plain"
    response.body = dump_request( request )
  end
  
  def do_POST( request, response )
    response.status = 200
    response['Content-Type'] = "text/plain"
    response.body = dump_request( request )
    response.body << request.body
  end
  
  def dump_request( request )
    request.request_line << "\r\n" <<
      request.raw_header.join( "" ) << "\r\n"
  end
end

if __FILE__ == $0
  port = (ARGV[0] || 2000)
  server = WEBrick::HTTPServer.new(
     :Port => port,
     :DocumentRoot => File.join( Dir.pwd, "/html" )
   )
  server.mount "/dump", PostDumper
  trap( "INT" ) { server.shutdown }
  server.start
end

If I run the above and point my browser at http://localhost:2000/dump I get:

GET /dump HTTP/1.1

Host: localhost:2000
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1) Gecko/20061026 BonEcho/2.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

I've also got a little html form that points to the same URL for its action. Submitting that form gives me:

POST /dump HTTP/1.1

Host: localhost:2000
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1) Gecko/20061026 BonEcho/2.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost:2000/form.html
Content-Type: application/x-www-form-urlencoded
Content-Length: 85

submit=Submit&text_input=Single+line+text&file_input=&textarea=Multi-line+text+input.

There! It turns out that POST data is just key/value pairs that are url-encoded. Each pair is separated by an ampersand.

The response from the server can also be instructive. If I use telnet to generate a GET request:

~$ telnet localhost 2000
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1

HTTP/1.1 200 OK 
Last-Modified: Thu, 11 Jan 2007 16:36:39 GMT
Connection: Keep-Alive
Date: Thu, 11 Jan 2007 20:09:56 GMT
Content-Type: text/html
Etag: 2a8766-169-45a66797
Server: WEBrick/1.3.1 (Ruby/1.8.2/2004-12-25)
Content-Length: 361

[...]

There's the response from the server. One thing that this program can't show you concerning the HTTP protocol: lines are terminated with the '\r\n' character sequence. This includes the blank lines, which are important to the protocol. A blank line separates the header (including the request line) from the content.

There you have it: a WEBrick servlet in less than 50 lines of code. Did I miss anything?

11 October, 2006

Tim Bray on TDD

I would say that, looking back over the 20 years I've been doing this, that the 2 biggest developments in IT, most-significant, are Object-Orientation and Test-Driven Development, and I think that TDD is more important.
From an interview by Obie Fernandez on InfoQ. It's a nice read, I recommend it.

05 October, 2006

Yegge On Ruby

I first have to admit that I tend to find Steve Yegge's writings boorish at best. His post on Agile processes illustrates some of his worst. However, he has an entertaining writing style that keeps me coming back.

This brings me to an old post of his on resistance to Ruby. Specifically, the lack of automated refactoring tools in Ruby. When did refactoring become about pushing buttons in an IDE? It certainly never started there. Is it not interesting that the author of Refactoring, Martin Fowler, uses Ruby?

That said, I'm feeling a bit guilty of the whole push-button programming sickness myself. (Maybe Eclipse is a little too cool). I think it's time for me to pick up Refactoring again and give it a good re-read.

In the meantime, I think <gasp!> Steve is right: Ruby is a butterfly.

edit:    this article is a good companion to Yegge's article.