shinyblog

Wednesday, October 14, 2009

Java foreach loops on empty collections

I've been worrying about whether I need to check for null when invoking a foreach loop on a collection that might be empty. The answer is, nope, I don't need to check for an empty list; java just Does The Right Thing.
List<Object> list = new ArrayList<Object>();
logger.info("here's a list that was always empty: " + list.toString());
for (Object o: list) {
logger.info("here's an object: " + o.toString());
}
logger.info("done");

...yields this output:
INFO: here's a list that was always empty: []
INFO: done

These alternate ways of expressing the same loop also all execute without a problem, even for an empty list:

for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
logger.info("here's an object: " + o.toString());
}
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
logger.info("here's an object: " + o.toString());
}

That's just a detail that's been bugging me, and now I understand the behavior. For what it's worth, I couldn't find this issue addressed in the JSR.

Wednesday, April 22, 2009

best of ben

Ben Shine's Recent Work

Sunday, April 19, 2009

graphical diff for git on mac os x

I just configured git to use FileMerge for diffs. FileMerge is a pretty graphical diff tool. I couldn't find quite the right invocation via google, so here's what I did:

  1. Create ~/bin/git-diff-driver.sh with these contents:
    #!/bin/sh
    /usr/bin/opendiff "$2" "$5"

  2. Make it executable
    chmod ugo+x ~/bin/git-diff-driver.sh


  3. Make git use this little script for diffs. Edit ~/.gitconfig to include these lines:
    [diff] 
    external = "/Users/ben/bin/git-diff-driver.sh"


Now the next time that you call git diff HEAD FileMerge will open. GUI sweetness.

Monday, February 23, 2009

missing out on flex?

Last week I finally started using an AIR application, TweetDeck, because my brother said it was cool. Now I'm reading about Flex and AIR, and I have to say, I might have been missing out on a good thing. It looks to me like Flex and AIR are together a powerful front-end platform for building nice applications... where by nice I mean the things that Ben Shine traditionally loves: smooth, swoopy, delicate, rounded, subtle, surprising, shiny.
This bears investigation.

Thursday, February 19, 2009

what's running on port 8080?

I learned an important new unix command today: lsof. The name seems to stand for "list open files." The purpose of the command is to list information about the process who has opened a file. In unix-y OS's, sockets are file-ish, so lsof -i :8080 lists the process who opened the file named port 8080 on localhost, where ":8080" is interpreted as the address of a network file.
In my case, I traced the rogue 8080 to an instance of tomcat being started up by ~/Library/Caches/IntelliJIDEA70/tomcat_Unnamed_adomainahexid. I could tell from the domain name that this was a tomcat that I was developing with four months ago. Ouch.
I don't know why it was starting at system startup, but I'm not in the mood to dork around (anymore than I have already), so I rm -rf'd the cache directory and moved the tomcat install to apache-tomcat-6.0.18-hideme. It's gone now.

Friday, February 06, 2009

something else to hate about outlook 2003

When I reply to an email in Outlook 2003, the display of the original email in my inbox updates with the helpful annotation, "You replied on 2/6/2009 at 2:41 PM." That's fine.
What sucks, though, is that Outlook applies that annotation before I've actually sent the reply. There's a time period when I'm composing the reply during which Outlook claims that I've sent a reply to a message, but I I haven't actually replied yet.
Ways in which this might be disastrous are left as an exercise to the reader.

Tuesday, January 06, 2009

o glorious patterns (of enterprise application architecture)

Two years ago, I started reading Martin Fowler's book, Patterns of Enterprise Application Architecture, on the recommendation of Adam Wolff, whose technical acumen I respect deeply. My first few times attempting the the book, the pages seemed to be made of a soporific variety of lead. I understood the words and the sentences and the paragraphs, but couldn't summon any interest in them.
Today at work, I somehow signed up to give an introductory talk on design patterns, so I went looking for my copy of the Gang of Four. I couldn't find it, but I did find PEAA. I opened the cover and found a list of The Most Amazing Things Ever. Four patterns describing ways to represent complex class hierarchies in databases! Two different patterns for storing session state! Query objects! Remote facade! Value object! Service stub! Finally, here was a vocabulary for the architectural problems that have challenged and puzzled me for the last two years! O glorious book! Just reading the inside front cover has crystallized hours of design discussions and a comparative analysis of a dozen web application frameworks. This is beautiful stuff!
Now I see why Adam was so excited about PEAA two years ago, and why I wasn't, and why I am now. If you're not building enterprise applications, there's no reason to care about the patterns. Studying them is dry and, joyless. If you are building enterprise applications, you spend your best moments thinking about the issues addressed by these patterns. If you're lucky enough to work with other people -- and really, who builds an enterprise app alone? -- then you spend hours each day talking about these issues. Beautiful, beautiful, glorious book!

Thursday, December 25, 2008

SOLUTION for "Rails requires RubyGems >= 1.3.1" problem

If you don't care about running Rails 2.2, you can safely ignore this post. If you ran into the same problem I did, this post will help you solve it.
I'm running Aptana Studio 1.2.1 with RadRails 1.0.0, and I'm creating a new Rails project using Rails 2.2.2. The wizard for a new RadRails project seemed to basically work, but it failed on starting the rails server with this error message: "Rails requires RubyGems >= 1.3.1 (you have 1.2.0). Please `gem update --system` and try again." I tried that several times and it didn't work. Some googling revealed a solution, but the solution isn't quite spelled out in n00b-friendly language. (cwilliams on the aptana support site does the best job yet, though) So here we go.
Prologue: A lecture from your friendly sysadmin. Never run commands that start with "su" if you don't know what they mean.
Body: (much cribbed from cwilliams again)
[ben@pro ~]$ sudo gem update rails   # get the latest version of rails
[ben@pro ~]$ sudo gem update --system # update the RubyGems system software
[ben@pro ~]$ gem install linecache # install the "linecache" gem

linecache is a requirement of RadRails that isn't listed in the requirements.
[ben@pro ~]$ ruby -S gem --version
1.2.0

That tells me that I've got version 1.2.0 of gem installed. Gem is ruby's package manager. So let's install a gem whose purpose is to update the gem system. This is a little complicated, but it works:
[ben@pro ~]$ sudo ruby -S gem install rubygems-update 
Password:
Successfully installed rubygems-update-1.3.1
1 gem installed

Good. Now run the script that updates rubygems...

[ben@pro ~]$ sudo ruby -S update_rubygems
Installing RubyGems 1.3.1
mkdir -p /Library/Ruby/Site/1.8
mkdir -p /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin
...

At the end of the output of the update_rubygems command, you'll see a long message from the RubyGems team. I'm pretty sure you can safely ignore it. Make sure you have the right version of gem installed now:
[ben@pro ~]$ ruby -S gem --version
1.3.1

Good. Now go back to Aptana and start your Rails server again: Window -> Show Views -> Servers. Right-click on the server named <project>Server. Select "Start server in debug mode" from the context menu. The status of the server should switch to "Starting." Right click on the server name again; select "Open Console/Shell." This should show a lovely shell whose output ends with
** Mongrel 1.1.4 available at 127.0.0.1:3001
** Use CTRL-C to stop.

Don't be frightened that all that text is in red. You're good, you're golden; rails is up and running.

Wednesday, December 03, 2008

two firsts

One, I wrote code with GOTOs. I'm setting up a highly constrained dev environment for my current contract. It has to be Windows XP, and it can't use cygwin. There are at least two different builds I have to run: one uses ant 1.6.5 and a vendor-specific implementation of jdk 1.4.2; the other uses Sun's jdk 1.4.2 and ant 1.7.0. In bash land, I'd just write a setup-foo.sh script and be done with it. In pure-windows windows, that's not going to fly. (Even if I could use cygwin or mingw, ant command-line parameters in cmd.exe get really messy when invoked from bash. You can only do backtick cygpath -w so many times before going insane.) So, finally, a generation after it was released, I had to learn a little bit of dos scripting. I started with a book called "Microsoft Windows Shell Script Programming for the Absolute Beginner" and I felt like an absolute beginner. How do I express conditional logic? [if cond ( ... ) else ( ... ) actually kind of easier than bash] How do I accept command-line parameters? [%1%, %2%, not unlike bash]. How do I call procedures? OMFG. CALL :SetupFoo. How do I return from procedures? Aiee! GOTO. I got to experience the joy of debugging code with GOTOs without an interactive debugger. Thanks, but no. Props to all of you who lived through that (hi, Pop) but I'm way happier with structured programming. Object-oriented programming, now, that's for the young kids... (Just kidding -- people my age can handle OOP; aspect-oriented programming is for the young kids.)
Two, I spontaneously generated a really nice roast chicken recipe. Occasional post-workout brunches at Boulette's Larder have encouraged me to experiment with embarassing amounts of butter and carmelized onions. Spud has been delivering a frozen organic bone-in chicken breast each week, and they were stacking up in my freezer; plus Trader Joe's had some really cute multicolor pearl onions. And there are insane cranberry sauces everywhere these days; I went with one from Bi-Rite that included apples and ginger. Combine that with my housemate's well-seasoned cast iron pan and a gas oven... Mmm. Yummies.

Friday, November 28, 2008

aptana studio upgrades the IDE paradigm

Aptana Studio is a sweet little IDE, but it gets even sweeter now that they've added in Jaxer and Cloud.
My development life has been veering away from Java and towards JavaScript lately. I'd been coding in IntelliJ IDEA 7.04. It's got intense suites of features for java web development. IntelliJ IDEA 7 is pretty darn nice for javascript, css, and html; until Wednesday, it was my editor of choice. (Version 8 has added some promising javascript support, but I haven't upgraded yet.)

But Aptana Studio has delivered a game-changer: the IDE provides integrated deployment to cloud servers. This is sick, sick, sick. Usually, in order to make a web site available publicly, a developer has to sign up with a hosting provider, register a domain, point DNS to the right name servers, configure Apache, and upload files to the right place, configure Apache some more, etc. That's not rocket science, but it's not what I want to spend my time doing. I want to sit down in the morning and have a proof-of-concept site running by midnight. (Registering a domain and provisioning a site usually takes at least 24 hours.)

Aptana Studio delivered my one-day web 2.0 proof-of-concept deployment goal. Here's how!
  1. Aptana provides a virtual hosting service, Aptana Cloud.
  2. I can sign up for and provision a cloud server from within Aptana Studio; they've got a brilliant 21-day-free-trial for a cloud server.
  3. Standard stuff I'd expect from a virtual hosting provider: Aptana gives me a subdomain, name of my choice, and handles routing. At install time, I can choose which servers I wan to install.
  4. I write some javascript and html code -- pretty standard stuff.
  5. In one operation, inside the IDE, I deploy my site to the cloud. Boom. There it is.
  6. I edit the code. Another cloud sync, and my modified code is running on the remote site.
  7. I can monitor my cloud's logs within the IDE.
Really, that's more like ten minutes -- so I got to spend the rest of the day actually writing code. Which is what I'm going to do now -- my review of Jaxer will have to wait.