2008-07-27

Porter Square apartment for rent

Email rent3@kasperowski.com

3 bedrooms
1.5 bathrooms
975 square feet

Includes parking, private laundry, private storage, private back yard space

Well maintained apartment on tree-lined cul-de-sac
Recently renovated, open floor plan
2 blocks from the Porter Square T and commuter rail station
Near Davis Square
A short walk to shopping, restaurants, parks, yoga, martial arts,
Leslie, Harvard, elementary schools, etc.

$2150/month
No fee









2008-07-23

Spring Integration

Mark Fisher of SpringSource gave a talk on Spring Integration at Monday night's Boston Java Meetup. Mark has been with SpringSource for 2.5 years. He is a Spring committer and leads the Spring Integration project.

Spring Integration 1.0 is scheduled to be released in about 1.5 months. Spring Integration is an application of many of the ideas in the book Enterprise Integration Patterns and its related web site.

Spring
Mark began with an introduction to Spring. Fundamentally, Spring is an inversion of control (IoC) container, offering dependency injection, aspect oriented programming (AOP), and enterprise support libraries. It supports a POJO based programming model. He gave an overview of Spring features:
  • In Spring 2.5, you can use annotations instead of or in addition to the usual Spring XML configuration files.
  • @Autowired annotation
  • @Test annotation, the EasyMock library
  • AOP for transactions: uses the @Transactional annotation, delegates to the transactionManager that you wired in the XML config. Mark recommends using AOP for anything that's not in your business logic/problem domain, that you'll apply to numerous objects or methods. Doing so lets you focus on business logic.
  • JDBC templates, e.g. getSimpleJdbctemplate().query("select id, balance from account here customer_name=?", accountMapper, customer). In his example, he also uses a PramaterizedRowMapper. The advantage of the JDBC and other templates is that Spring handles the mundane set up work and exception handling for you.
  • JMS templates: Configuring a JMS listener is easy. They are a complete replacement for message-driven beans, and no EJB container required.
Some consequences of using Spring are that your domain model is simplified, layers enforce separation of concerns, and interface contracts promote loose coupling.

A meetup member asked why Spring uses AOP instead of @Interceptor. Mark replied that a problem with that approach is that you must annotate each method @Interceptor everywhere--you can't use AOP cut points defined by regular expressions, for example. He commented that it is still an open question whether EJB3's Interceptor approach is powerful enough

Enterprise integration patterns
Mark continued with an overview of enterprise integration patterns:
  • Pipes and filters architecture: conceptually, just like Unix pipes and filters
  • Message: send Messages through the pipeline. A Message is just a wrapper around a Java object.
  • Message channel: decouples producers from consumers. Can bepoint-to-point or publish/subsribe.
  • Channel adapter: connects a source to the messaging system. Can be anything, like a message bean, a web request, or a file system object.
  • Service activator: lets you invoke any POJO method without the service knowing that it's being using that way
  • Message translator: a payload transformer, converts the type or format of a message
  • Content enricher, content flter: add to or remove from message content
  • Content based router: determines the target channel based on payload type, property value, or header attribute. Decides where to send message. For example, the router might send a message to either the VIP service or the standard service based on importance of sender.
  • Splitter and aggregator
Spring Integration API
Following that, Mark presented the Spring Integration API. In a nutshell, Spring Integration implements enterprise integration patterns in Spring. The primary implementation points are:
  • interface MessageSource.receive: receives messages
  • interface MessageTarget.send: sends messages
  • interface MessageChannel.send, .receive
  • interface MessageHandler.handle
  • Message Bus: aware of components (hadlers, sources), connects them to channels, turns everyting on, runs a task scheduler, creates message end points, and ties them to channels
As a user of Spring Integration, you will specify things in your XML config file or via your annotation-based configuration, e.g. @Handler. You won't, for example, implement the MessageSource interface directly in your business code. This is consistent with Spring's theme: use domain objects everywhere; don't write any special messaging code.

Mark showed us some great demos and code examples, all of which are included in the Spring Integration distribution.

Additional features on the Spring Integration road map include:
  • Additional XML support, including XSLT transformations
  • Quartz scheduling
  • Support for additional channels, including RMI, email, and more

2008-07-16

How to assemble the Shaker all in one loft bed

This is a pictorial guide to assembling the Shaker All in One Loft, sold in the Boston area at Bedrooms. This series of photos is my step by step disassembly, with the photos reversed for assembly.

At Bedrooms, the bed is called "Shaker All In One Loft Twin/Twin" and is item #2000. For cross reference, a label on the bed calls it the Innovations Model # 261 Shaker ALL IN ONE TWIN, from Hartford, CT.

This catalog image from Bedrooms shows the bed completely assembled in its model habitat:



Here are the step by step assembly photos:























































Done!

Here is the simple command line I used to rename the photos and sort them from disassembly order to assembly order:
$ n=0; for f in `ls -1 *.JPG | sort -r`; do newname=${n}.jpg; if [ $n -lt 10 ]; then newname=0$newname; fi; mv $f $newname; n=$(($n+1)); done
My original photos were 8 megapixels each. To resize the images to 1024x768, I used ImageMagick and this simple command line:
$ for f in `echo 2008-07-13-jake-bed-disassembly/*.jpg`; do convert $f -resize 1024x768 2008-07-13-jake-bed-disassembly-1024x768/`basename $f`; done

2008-07-15

Location: OpenCellID and WIGLE

I have been thinking about mobile location based services (LBSes) for a long time. My typical user story is, "Alice and Bob are eating dinner in a restaurant. They decide they want to see a movie. Using her phone, Alice looks up nearby movies, theaters, and show times and buys two tickets to the next showing of a fun movie. They pay their bill and go to the theater." Other user stories have them looking for a cafe or a night club. Whatever it is, they are away from their home PCs, they have a mobile connected device, and they want information that is relevant to their current location.

Moviefone's mobile web site solves the user story. You tell it your zip code, and it tells you about the movies, theaters, and show times near you. One problem with this is that you might not know your current location's zip code. Another problem is that zip codes are geographically large. The nearest movie theater in my zip code is two miles away, but the nearest movie theater is only one mile away, in another zip code. The ideal LBS automatically knows where you are and has good precision.

The iPhone Google Maps application is compelling because it locates you automatically, using cell tower triangulation, WiFi access points, or GPS on iPhone 3G. In one very poorly controlled test I conducted, it takes about 5 seconds for Maps to locate you by cell tower, another 5 seconds for the more accurate and precise WiFi location, and another 20 seconds or so for the very accurate and precise GPS location. (These are very rough timings, to be taken with a grain of salt.) iPhone exposes this to developers through the Core Location API. On Windows Mobile, Google Gears exposes a similar API to developers. What APIs are available to other developers, or to developers who want a generalized way to locate the mobile user?

OpenCellID is an open database of cell tower IDs and their geographic coordinates. The first problem is that it is incomplete. For example, there are no database entries for cell towers in Western Massachusetts or on Cape Cod. You might be able to pay another provider for more complete data, but you would encounter the next problem: it is difficult to obtain the local cell IDs through the phone. Most handsets do not expose location data, through JSR-179 or any other accessible API, and carriers do not expose cell tower IDs through WAP HTTP headers. Finally, cell tower based location is not precise enough to solve some problems, such as what street am I on. On the positive side, finding location by cell tower is fast, and might be precise enough for some applications (what city am I in?).

WIGLE is an open database of WiFi access point SSIDs and their geographic coordinates. WIGLE's static and interactive maps show the amazing density of WiFi access points in urban areas. In the city, a WiFi based location can be very accurate, and precise enough and fast enough for most applications. The advantage over GPS is that it works inside buildings, where GPS might not work. The primary disadvantage is that the device might not have a WiFi radio or it might be too far away from a WiFi network. (Thanks to the Adeona FAQ for pointing me to WIGLE.)

If you are building a location based service, cell tower ID and WiFi access point SSID are two pieces of information that you might be able to use, either in the absence of GPS or as an alternative to GPS. WiFi SSIDs are probably the best approach for users stories like "Alice and Bob are eating dinner in a restaurant..."

2008-07-12

Critique of iPhone Dvorak keyboard

Unfortunately, the iPhone Dvorak keyboard hack isn't as good as it could be. There are two problems with it. First, the key clue is Cyrillic, not English. By "key clue," I mean the key that the keyboard displays above your thumb. When you press a key, the key is displayed above your thumb, and the keyboard doesn't type the key until you raise your thumb. This improves your typing accuracy because your thumbs obscure the keys, and you can move your thumb around the keyboard until you find the key you want, then release. While I can touch type Dvorak, touch typing doesn't translate directly to thumb typing. I need the key clues. The key clues, though, are Cyrillic, so they are useless for English.

The other problem is the lack of autocompletion. When I type English words on the QWERTY keyboard, the iPhone does a great job correcting my mistakes, and it learns my peculiar vocabulary and jargon to its autocompletion dictionary as I go. As with the key clue, this is a great boon to typing accuracy. The Cyrillic based Dvorak hack does neither--there is no autocompletion. The only way to correct your mistakes is to actually correct your mistakes. (It's funny how we whine about things not working well, when they didn't even exist five or ten years ago.)

So while it's nice that there is a Dvorak keyboard hack, in practice, I rarely use it. I thumb type QUERTY on the iPhone, just as I would on any other phone, and touch type Dvorak on the PC's full size keyboard.

2008-07-07

Why doesn't Capture work?

Capture 0.1 stopped working properly on my iPhone. When I tap it, the Capture start screen appears, as expected. But when I tap the Launch Capture button, the screen blanks and SpringBoard reappears, but Capture isn't running. rubycon5 has a similar problem, so I know it's not just me.

I notice that when I launch Capture from the SpringBoard, it runs as user mobile:
mirex:/Applications/Capture.app root# ps -ef | grep Capture
501 660 622 0 0:00.22 ?? 0:00.97 /Applications/Capture.app/Capture --launchedFromSB
0 670 632 0 0:00.01 ttyp0 0:00.01 grep Capture
mirex:/Applications/Capture.app root# grep 501 /etc/passwd
mobile:*:501:501:Mobile User:/var/mobile:/bin/sh
mirex:/Applications/Capture.app root#
When I log in as mobile and run Capture from the command line, it logs some errors to stdout:
mirex:~ mobile$ cd /Applications/Capture.app/
mirex:/Applications/Capture.app mobile$ ./Capture
2008-06-28 10:41:52.185 Capture[681:d03] MainView initWithFrame
2008-06-28 10:41:52.212 Capture[681:d03] MainView initWithFrame end
2008-06-28 10:41:52.526 Capture[681:d03] from: (null), to: (null)
launchctl: CFURLWriteDataAndPropertiesToResource(/Library/LaunchDaemons/com.digitalagua.capture.plist) failed: -10
launchctl: CFURLCreateDataAndPropertiesFromResource(/var/mobile/Library) failed: -10
launchctl: propertyList is NULL
launchctl: no plist was returned for: /var/mobile/Library
launchctl: no plist was returned for: /var/mobile/Library
launchctl: CFURLCreateDataAndPropertiesFromResource(/var/mobile/Media) failed: -10
launchctl: propertyList is NULL
launchctl: no plist was returned for: /var/mobile/Media
launchctl: no plist was returned for: /var/mobile/Media
mirex:/Applications/Capture.app mobile$
CFURLCreateDataAndPropertiesFromResource error -10 is kCFURLUnknownError, which is interesting but not very helpful.

My work around is to log in as root and run Capture from the command line. Running as root, it has no problems.

I have tried both tweaking file permissions and reinstalling Capture to no avail. Have you solved this problem? How?

2008-07-04

Using rsync and ssh to copy music from iPhone to iTunes

I wanted to copy my music library from my iPhone to my PC at the office. iTunes make it easy to sync files from your PC to the iPhone, but not from the iPhone to a second PC, so most people resort to file copying. Smart people use rsync for efficient synchronization between multiple file systems, so I thought I'd give it a try. Here's how I did the same to sync the iPhone to the PC.

First, both computers must have rsync and ssh installed. I use a jailbreaked iPhone, with rsync and ssh installed through Cydia. My PC runs Windows XP, with rsync and ssh installed through Cygwin.

On the PC, I opened a Cygwin bash console and typed the rsync-over-ssh command. I typed my iPhone root password at the prompt, and watched until it finished copying all the music files:
richard@richard ~
$ rsync -e ssh -r --progress root@192.168.2.106:/var/mobile/Media/iTunes_Control/Music "/cygdrive/c/Documents and Settings/richard/My Documents/My Music/mirex"
root@192.168.2.106's password:
receiving file list ...
848 files to consider
Music/F00/ABBR.mp3
4733652 100% 5.27MB/s 0:00:00 (xfer#1, to-check=845/848)
Music/F00/AGWS.mp3
6498462 100% 7.29MB/s 0:00:00 (xfer#2, to-check=844/848)
Music/F00/BEIE.mp3
...
4724362 100% 559.84kB/s 0:00:08 (xfer#833, to-check=0/848)

sent 7276198 bytes received 974657842 bytes 393639.62 bytes/sec
total size is 3559603155 speedup is 3.63

richard@richard ~
$
In iTunes, I clicked File / Add a Folder and added My Documents/My Music/mirex. I waited a few minutes for iTunes to import the music files, and everything was ready to play.

There are at least two advantages to this approach:
  • rsync-over-ssh is faster than Windows file copy or scp because it skips files already exist on the PC.
  • This is completely wireless. You don't have to cable the iPhone to the PC.