Dear Nintendo: A Wii Storage Solution, Please!

We have a Wii. We’ve had it pretty much since they hit the market. We love it, yes Wii do. Except for one thing: the unbelievably small amount of internal storage the thing has. It only has 512M of storage that is used for game save data. For people who don’t have a lot of games, that’s probably plenty. It was plenty for us, too, until we started buying lots of games and downloading games from the Shop Channel. I can’t tell you how many times we’ve wanted to download something new from the Shop Channel, only to be told we don’t have enough free space. Some of the games, especially the old console games, are tiny. Most take up only a single “block.” But some, like the episodes of Strong Bad’s Cool Game For Attractive People, and the save file for Super Smash Bros. Brawl, are huge. As in hundreds of blocks, huge.

So, what can we do? Well, there’s an SD slot on the front, and we have a 2G SD card in there. But that’s considered completely separate from the internal storage, and none of the games that we have can run with their data file on the SD card. On a few occasions we’ve moved things temporarily to the SD card to free up space on the internal storage, but if we ever want to play that game again, we have to shuffle files around again. Guitar Hero World Tour will, apparently, let you keep downloaded songs on an SD card, but the kicker is that you can only download them to the internal storage and then copy them. But when you already don’t have enough space on the internal storage, you’re still screwed. And last night when I fired up Rock Band 2 for the first time, it told me that it could store “extras” and such on the SD card, and was that OK? I said it was, and it then told me that I didn’t have enough free space to install the bits that would allow me to keep stuff on the SD card. Grrrrr.

There are two USB ports on the back of our Wii. I have an external drive that’s something like 150G that I’m not using for anything. It’s not even plugged in. If Nintendo would allow it, I could plug that into the Wii, and our storage problems would be solved. But they don’t allow that. Well, it’s not that they disallow it, it’s just that plugging the drive in won’t do anything. They have to patch the OS to make it look in other places for data files. And they can do that; they’ve just chosen to ignore the pleas of their users. Much the way Apple has turned a deaf ear to our demands for cut & paste on the iPhone, Nintendo has gone far too long without giving us a reasonable storage solution. My cynical friend is convinced that the solution will be to buy a new “Nintendo Wii Version 2, Now With More Internal Storage!” I sure hope he’s wrong.

Come on, Nintendo, give us a workable storage solution. Soon!

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Objective-C 2.0 Properties Are Needlessly Verbose

I’ve been working in Objective-C for a little while now; not quite two years, off and on. I was really excited when Apple announced that Objective-C 2.0 was going to have generated properties, but the syntax they gave us leaves me flat, as it is needlessly verbose.

For those who don’t know, in Objective-C 1.x, if you had an instance variable in a class that you wanted to expose, you had to provide getter and setter methods for it, just like you do in Java, C++ and several other OO languages. You would see something like this in MyClass.h:

1
2
3
4
5
6
7
@interface MyClass : NSObject {
    NSString *name;
}
 
- (void) setName: (NSString *) aName;
- (NSString *) name;
@end

and then in MyClass.m, you would see this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#import "MyClass.h"
 
@implementation MyClass
- (void) setName: (NSString *) aName
{
    [aName retain];
    [name release];
    name = aName;
}
 
- (NSString *) name
{
    return name;
}
@end

Objective-C 2.0 promised to eliminate all that boilerplate code in your *.m files for getting and setting variables. But they did it in a strange way. Now, in MyClass.h, you would see this:

1
2
3
4
5
6
@interface MyClass : NSObject {
    NSString *name;
}
 
@property(nonatomic, retain) NSString *name;
@end

and then in MyClass.m, this

1
2
3
4
5
6
7
#import "MyClass.h"
 
@implementation MyClass
 
@synthesize name
 
@end

Now, it certainly cut out quite a bit of code for the getter and setter, but why do I have to declare the type of the property twice? You have to declare the instance variable as usual, but then you also have to specify the data type again when you add the @property declaration. There’s no reason I can think of that those two lines couldn’t have been combined into the variable declaration. Objective-C already has tokens that are ignored, such as IBOutlet, so it shouldn’t have been an issue with breaking the parser. And the @synthesize declaration in the *.m file is annoying, but I guess it was necessary to keep the properties from being auto-created in the wrong place.  In my opinion, this is what property declarations should look like

1
2
3
4
5
@interface MyClass : NSObject {
    @property(nonatomic, retain) NSString *name;
}
 
@end

That’s it. No duplication. Simple. Elegant.

Can anyone think of a good reason why they didn’t do it like that?

12/28/2008 15:13:23 Update: As Ahruman pointed out in his comment, I misspoke about IBOutlet. It is not actually ignored, but is used to tag an instance variable for use by Interface Builder. Sorry for the confusion. And be sure to read his comment below. It’s packed with good info that I didn’t know.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Christmas Kindness At Red Robin

Tonight Thomas and I needed to get some victuals, so we decided to go to Red Robin. You may remember the last time we went there and were less than impressed. But Thomas wanted to go there and I was in the mood for a mess o’ fries, so I agreed.

After we were seated, our waiter came over wearing a Santa hat with “Bah Humbug” embroidered on the front. Thomas complimented him on it and he said that it actually belonged to his manager. We placed our drink orders and he left. He came back a few minutes later with the drinks, and told us that he was leaving for the night, and would be turning us over to someone else. I can’t remember her name. 

About ten minutes later, he came back over and put the Santa hat on Thomas’ head. He said that he had talked to his manager, and he said to give him the hat. It was quite a nice hat, actually. Anyway, Thomas thanked him and then asked who the manager was, so he could thank him, too. The manager, Kyle, came over and chatted with Thomas for about five minutes about topics including our plans for Christmas, his plans for Christmas, our new puppy, his dog called Leroy Brown (I asked if the dog was “bad, bad” and he smiled at my recognition of the reference), and the puppy he’s bought for his brother. Thomas thanked him for the hat again, and then he left.

I was really surprised at this gesture. Thomas didn’t compliment the hat in such a way that he was trying to get it; he just said that he liked it. It was very nice of both Kyle and the server to give it to him. We’ll definitely go back and eat there again. And Thomas has already told me he wants to ask if Kyle is in, so they can chat again.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Socialized Trash Hauling Derailed - For Now

A few months ago I heard that the august leaders of Gwinnett County, GA (where I live) had decided that we’re all too stupid to decide for ourselves who we want hauling our trash. In an effort to assist us with our daily lives, they decided that they would administer all trash hauling in unincorporated Gwinnett themselves, with every homeowner being forced to abandon their current haulers and use the one appointed to them by the county. Do you believe that crap?

I have received two bills from my new county-mandated hauler, which I haven’t paid yet. And I’m glad I haven’t paid them. In a moment of sanity, Judge Michael Clark has issued an injunction to stop the program, leaving the existing haulers in place until a formal hearing can be held. Two of the ousted haulers have alleged that the county overstepped its authority and that the contracts are illegal. Whatever the reason, this next step towards total government control of our lives has at least been delayed, if only for a little while. Every story I’ve read about this has called it the county’s “controversial” plan, yet I haven’t heard much about it on the local media. What I do know is that the county had no meetings or announcements about the plan before it was finalized. When something like this is done by government in secret, you know it’s bad news.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Hollywood Release Windows Suck

A couple of weeks ago I extolled the virtues of my new Netflix Player. I’m still thrilled with it, but the other day I happened to be looking at my instant queue from a web browser, and I noticed several lines in the queue that looked like this

Netflix Instant Queue

Notice anything about that? Yeah, it’s the “Available Until Dec 31, 2008.” WTF? Out of 53 entries in my instant queue, 9 of them will no longer be available after January 1, 2009. That really, really sucks. According to this article and this one, the reason for this is something called “release windows.” These are time periods that the movie studios allow their movies and shows to appear in a given format. Basically, after a certain amount of time, the studios yank content from one medium, such as downloads, and make it available on another, such as broadcast TV. According to the articles, that’s what the studios think will rake in the most money. It seems to me that the best way to maximize profit for a movie or show is to maximize exposure. This means making it available in as many formats as consumers are willing to pay for, for as long as possible. This would give consumers the most flexibility in how they watch the content. And maybe, just maybe, if it were super easy to legally watch the content that people want to watch, piracy would decline. I’m just speculating on that one, of course.

I understand that businesses have to make money to stay in business, but I’m really not happy that 17% of my queue will evaporate on January 2.

Thanks, Hollywood.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Three Days With the Roku Netflix Player

My Netflix Player arrived on Wednesday. It was supposed to be a family Christmas present, but you know how those things go. When something this cool arrives this early, there’s no way it’s going to stay boxed up for three more weeks.

The box is very small, maybe 4.5 inches on a side, and about 2 inches think, and it will fit easily next to our DVD player. Installation was absurdly easy. I attached it to the A/V input jacks on our DVD/VCR and plugged it in. I was planning on connecting to the Internet using my WiFi router, and as the player was coming on, I told the family to pray that it supported WPA2, and not just WEP, because if it didn’t, I’d have to reconfigure the router. Fortunately, it did support WPA2, and within about 30 seconds of connecting the A/V wires, it was online.

After it phoned home, it gave me a code that I had to enter at netflix.com to tie the box to my account. I did this on my laptop and almost before I could pick up the remote again, the screen had changed and was telling me that everything was now set up.

The first screen you see is your “Instant Queue.” This is a CoverFlow-like page which shows you the covers of all the videos in your Instant Queue. This is the one thing that I don’t like about the player: you can’t search for things to watch using the player itself. You have to go to the website using a computer, find what you want and stuff it into your Instant Queue. Once you do that, it shows up on the player within seconds. This is a bit hokey, and they really should have come up with a better solution. However, this is my only real complaint about the thing.

We did get off to a slightly bad start, though. The first thing we decided to watch was an episode of Doctor Who from 1974, featuring the One True Doctor™, Tom Baker. (Nothing against the current fellow, whom I like quite a bit.) I clicked the Play button and it started buffering. And buffering. And buffering. After about three minutes, it started playing, but within 30 seconds, it was buffering again. This was discouraging, but we decided to try something else, and the problem seems to be with this particular episode, as everything else has worked flawlessly.

The way it works is after hitting the Play button, the player buffers for about 30 seconds, then it starts playing. That’s it. You can pause and restart. You can rewind and fast-forward, though this is a bit klunky. What I really like is that if you stop watching a show and come back later, it remembers where you left off. I don’t know how many shows it will remember, but it’s at least one.

So, what did we watch? First, I watched the wonderful concert movie by Talking Heads called Stop Making Sense (it never gets old). Then we watched the first episode of the original (and best) Battlestar Galactica series. We then moved on to season 1 of The A-Team. Those things Thomas and I watched together. After he went to bed, I watched the first episode of season 2 of 30 Rock. We’ve also got season 1 of the original Knight Rider, Buck Rogers and Airwolf in the queue. Lots of great, old shows.

We were slightly disappointed that several of the shows Thomas was hoping for are not available for instant viewing. These include Fraggle Rock, Invader Zim and The Muppet Show. Perhaps these will be added later. Netflix currently has 100,000+ DVDs, but only 12,000ish of these are available for instant viewing. I have to believe this number will increase.

(I should note that they do seem to remove the ability to stream some DVDs occasionally. When they first announced support for OSX, I watched part of Purple Rain, just to test it out. Purple Rain is no longer available for streaming. I don’t know why, but it isn’t.)

So, after three days, we all love the Netflix Player. For us, it was certainly worth the $100 it cost.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Let *Me* Decide What A Good Password Is!

I have had it with web sites that won’t let me put really secure passwords on my accounts. What do I mean by that? I mean sites that won’t allow anything other than letters and numbers in a password. WTF? I have a whole keyboard full of lovely glyphs to choose from; why limit me to 52 letters (upper and lower, assuming the developers are smart enough to know the difference) and ten digits?

By placing non-alphanumeric characters in a password, I am making it much harder to guess or crack. Yet there is a corps of web developers out there who force me to choose less secure passwords, because they won’t let me put punctuation in them. Why they do this, I can’t say. There is not a single compelling reason to exclude punctuation from passwords. Not one. I challenge any of you to give me a good reason for this restriction. In fact, it’s more work for the developers to check for these “offending” characters and scold the user for daring to use them! I’ve been stewing about this for a while, but this morning when I tried to setup an account at podiobooks.com and was told my password was not good enough for them, it sent me over the edge.

So, tech managers, here are your marching orders: Look at your site(s). If you have a restriction on what characters can go in a password, figure out which of your developers wrote that code, and fire them. Then, have someone else rewrite that bit of code the right way.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

The Case Of the Too-Hot Transformer

Picture it. Friday night. 22:45. Outside Atlanta, GA. Cold. The wife and I were watching the final episodes of Season One of Burn Notice. Killer show. From the other room came a howl of consternation. Thomas gave it to me straight, “Dad! Can you check our Internet connection? Every website I try to visit gives me an error!” Once the episode ended, I went to work on the problem.

I checked the computer and, sure enough, it wasn’t connecting to the Internet. I then tried to ping one of the computers on the local network and it wasn’t responding, either. I checked the downstairs router and rebooted it, just to be sure. It came back up, but I still couldn’t get through it. I also couldn’t get my iPhone to connect to the router’s WiFi. 

I then headed upstairs to the data center. Actually, it’s my office, but there are a bunch of computers in there. I walked in and immediately noticed that the router (a SonicWall TZ 170) was off. Not good. I unplugged it and plugged it back in. Still bupkus. I then unplugged it and pulled the whole power cord and that’s when I felt it. The transformer in the middle of the cord was hot. I don’t mean slightly warm or somewhat heated. I mean hot as in, “Holy crap! That thing is hot!” 

The quest, then, was to find a replacement power supply amongst the boxes and boxes (and boxes) of old computer stuff that I keep for just such an occasion. I found one that fit and plugged it in. Some of the lights came on, but not all. I unplugged it and reread the label. Oops. The voltage was twice as high as it should have been. I continued looking through my boxes of computer cables and found another with the right size plug and the right voltage and amperage. I plugged it into the router, and up it came. And my wife thought there was no good reason to keep all that junk around. 

So why did the power supply fail/almost melt? I don’t know. It has been running 24/7 since 2004, but I would have expected it to last a bit longer. Oh well, it’s fixed now.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

iPhone OS 2.2 - Meh, So Far

I happened to be up and working for the man at 2:00 this morning when I saw a note on Twitter saying that Apple had released version 2.2 of the iPhone OS. Being the fanboy that I am, I immediately started the update process. The whole thing, from first click to iPhone ready-to-use, took about 15 minutes. Not bad, and certainly better than some previous upgrades.

Engadget has a rundown of the new features. One of the biggest additions is Google Street View, which lets you see street-level views while working through driving directions. You can also get walking directions from the Maps app, but since I never walk anywhere, that doesn’t really help me. The rearranging of the URL bar and Google box in Safari is another. You can also download podcasts over the air, but I use my 60 GB iPod for podcast listening, so this feature doesn’t do anything for me, either.

Basically, I’m just hoping that they’ve squashed bugs and made the OS more stable. I love my iPhone, but it does have its problems. I don’t know about everyone else, but I have to reboot my phone about once a week to keep it responsive. I know it’s time to reboot when I’m typing on the keyboard and I’m about 6 letters ahead of what’s shown up.

Oh yeah, Steve has still not decided that we’re worthy of copy & paste. Even though about 99% of iPhone customers are begging for C&P, it’s almost like Steve is keeping C&P away from us out of spite. Maybe in 3.0…

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

I Found My .emacs File! w00t!

As I lamented yesterday, I had lost my .emacs file. I searched all my computers that I thought I’d ever run Emacs on, but couldn’t find it. Then a few minutes ago, I checked my iBook G4, knowing there was no chance of a copy being there, but checking just for completeness. But there was a copy there! O joy! My .emacs and I are reunited at last. What’s funny about this is that I honestly don’t remember ever running Emacs on this laptop, it being such a puny little machine. To safeguard against losing this file again, I have now copied it to every machine I ever use, even if that machine doesn’t have Emacs installed.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

OH NOES! I’ve Lost My .emacs File!

I was first exposed to Emacs back in 1991. It took me a while to warm up to it, but I did and I have been using it ever since. Once I started using it on a regular basis, I started customizing it. You can write modules and such for it, but for simple customizations, you can just put them in a hidden file called .emacs in your home directory. As time passed, I would add various changes to my .emacs file, adding convenience functions in Lisp and other bits to make me more productive. As I changed jobs and changed computers, I always made a point of taking this file with me so I’d always have it.

When I switched from Windows to OSX in November of 2006, I didn’t immediately need Emacs, so I didn’t think to copy my .emacs file over. And once I didn’t need the Windows machine any more, I put Linux on it and turned it into a server. But guess what I forgot to do. Yep, I forgot to copy my .emacs someplace safe. I hadn’t noticed it was missing until today. I need to run Emacs for something and when I went to make a change to my .emacs file, that’s when I realized it was missing. I checked my backup drive, which has a bunch of stuff off that old PC, but my .emacs file was nowhere to be found.

Even though I haven’t used Emacs in a while, I need to now, and having that file sure would be nice. But even if I didn’t need to use Emacs right now, I’m still a bit sad to see the file go, since I carted it around for so long. Keeping one file with you for 15 years is quite a long time, wouldn’t you agree?

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Obamagasm: The Morning After

The election is finally over, and The Messiah has been elected. I had known for at least two months that McCain didn’t have a prayer of winning but now that it’s official, well, it pretty much sucks. Actually, it’s not truly official until the Electoral College delegates vote and they could ignore the popular vote, but that’s not going to happen. So, Obama is our new Lord and Savior, with his truckloads of “hope” and “change.”

I was watching the Twitter and Friendfeed streams last night as the networks called the election for Obama, and then while McCain was conceding. The comments from tweeters and friendfeeders was nothing short of embarrassing. You people who voted for Obama don’t realize what you’ve done to our country. I’ve said many times that McCain was an awful candidate, but he would have been a hell of a lot better for the country than Obama. It will probably take a year before the extent of the damage is truly visible, but at that point, it’s too late.

And, for the record, I don’t give a damn what “The World” wants. This was our election, not “The World’s.”

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

I Just Got Back From Voting

When I got to my polling station, the line was out the door, for about 150 feet or so. I queued up with everyone else at 8:00. It took me about an hour just to get inside the building, at which point I saw that it was much like Space Mountain at Disney World: the queue inside the biulding was far longer than the queue outside. All told, I spent two hours and fifteen minutes waiting in line. I have never spent that much time waiting to vote.

I took my iPod and my Greek grammar with me, so I was entertaining myself while I waited and didn’t really pay much attention to those around me. But there were two ladies in front of me who were talking the entire time. At one point, one of them took a call. After the call, she told her fellow voter, “My girlfriend just told me that Obama is going to put the entire world on a single currency! That’s, like, in the BIBLE and stuff!” Good grief. I considered asking her if she actually believed Obama was the Antichrist, but I decided against it. The girl who was with her just said, “Yeah,” and then continued to disparrage her absent husband’s appearance. She complained about how he’s lost most of his hair and his “six pack” is now a “two pack.” I considered telling her that based on what I could see of her, she shouldn’t really be complaining. Once again, I decided against speaking.

One thing I noticed is that there were handmade signs everywhere saying “NO CELL PHONES,” yet about every third person in line had their cell phone out and was using it for one thing or another. I myself got my iPhone out several times and posted updates to Twitter. As I got near the penultimate twist in the line, a poll worker approached and told me to put my cell phone up. He was telling everyone, not just me, but it was still annoying. He kept saying, “This is a polling place! No cell phones!” You know, I can understand disallowing cell phones as you interact with poll workers, or as you actually cast your vote. But restricting them while you’re in a two-hour line is just absurd. Being the law-abiding citizen that I am, I finished typing the email I was working on, sent it, and then put my phone away. Most people did not comply.

So, there you have my voting report. I did my part to stop The Messiah from ascending to the throne, but I doubt it will do any good. Too many people are caught up in this collective Obamagasm of all his “hope” and “change” and promises of moonbeams, puppies and ponies for everyone. Well, for everyone except those evil, wicked “rich” people who don’t “deserve” them and who are not paying their “fair share.”

The next four years are going to be interesting, to say the least.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Grails Podcast Mentions My Closure Post

Like other bloggers with an ego, I have Google Alerts set up to let me know when someone mentions me or my blog anywhere that Google knows about. I got an alert yesterday letting me know that I’d been mentioned on the latest episode of the Grails Podcast. How cool is that? Specifically, they mentioned my Groovy Sql Closure Examples post. Thanks, Glen and Sven, for the podcast love. :-)

I’ve been spending some time with Grails latest and have been really impressed with it. I spent a couple of hours on Saturday playing with it, seeing how much of my Rails knowledge was applicable to Grails. Quite a bit of it, actually. I really like what I’ve seen of Grails, so far. I’d probably have to use it on a real project to really get a feel for it, but it looks like it would be a nice environment to work in.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Reading the Dictionary Is Fun

While waiting for my lunch to cook today, I picked up my son’s Oxford Desk Dictionary to look up a word. I had the word “fop” in my head, and I wanted to make certain that I was correct in what I thought it meant. I was correct that it means a dandy, or an “affectedly elegant or fashionable man.” But that’s not where the fun came in. I happened to flip a few more pages, and I ended up learning two new words: funambulist and funicular.

The first, funambulist (fyu-NAM-byu-list), is another words for tightrope walker. The Oxford dictionary didn’t give any etymological info, but the American Heritage dictionary said it comes from Latin. fūnis, which means “rope,” and ambulāre, which means “to walk.” This word kind of reminds me of “pugilist” which is an old word for a boxer, and pugilism, which is another word for boxing. While you do still occasionally hear pugilist or pugilism, I’ve never heard a tightrope walker referred to as a funambulist.

The second word, funicular (fyu-NIC-yu-ler), means “(of a railway, esp. on a mountainside) operating by cable with ascending and descending cars counterbalanced.” I would never have guessed that’s what it meant if I had just seen it written somewhere. It sounds like something related to a funeral, to me. Now that I know what it means, I can describe the cable cars running to the top of Stone Mountain as a funicular cable car system. Neat, huh?

Will I ever use either of these words in normal conversation or writing? Probably not, but I don’t believe that learning is ever a wasted endeavor. Of course, if I ever get on Jeopardy!, they might come in handy.

 

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Greek and Spanish Simultaneously: Is It Possible?

Around April in 2006, I started learning Greek, because I wanted to be able to read the source materials of the New Testament (notice I didn’t say the “original” Greek). I worked on this pretty steadily until late 2007. At that point, I put Greek on hold in order to study Spanish with my son. I have continued to take my Greek bibles to church, but my skills have already begun to fade. I’m having to look up way too many things as I read, which makes it less than fun.

So, I need to go back and refresh the Greek, but I don’t want to abandon the Spanish. I’ve made really good progress in Spanish, and I’d hate to lose that progress. What I’m wondering, then, is if it’s possible for me to study both Greek and Spanish, at the same time? I think I can do it. I already spend around an hour at my computer every morning before I start work, so I could easily replace part of that time with Greek practice. I could then work on my Spanish in the afternoon, and in the car (I’m a subscriber to Coffee Break Spanish). Has anyone else attempted to learn two languages at the same time? Do seminary students learn Greek and Hebrew at the same time, or do they learn them sequentially?

I’m going to give it a go.

Wish me luck.

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Dear Apple: Some Java Love, Please?

I love your machines. Truly, I do. Back in 1988 I bought a toaster-model Mac SE, with one megabyte of RAM, and I loved it. It only had a nine inch, black-and-white screen, and I loved it. For various reasons, I sort of lost the love for a while, until 2006. I acquired an iBook G4 in a hardware trade with a friend and I quickly became hooked on the sweet goodness that is OSX. That was in August, 2006. Two months later I bought a Mac Pro, which I love so much I sometimes feel the need to kiss it goodnight.

But there’s one thing about the Mac that bothers me: lousy Java support. Sun handles JDK releases for Windows and Sun machines and every Linux system on the planet. Yet, for some inscrutable reason, you have decided to handle Java for OSX yourself. And, not to be rude, but I just have to say that you suck at maintaining Java for the Mac!!! Let me ’splain.

Sun released the first version of Java 6 for Windows, Linux and Solaris in December 2006. Two days ago, Sun released the tenth update for Java 6, again for Windows, Linux and Solaris. On September 24, 2008, you guys released Java 6_07, which was nice to finally get it, but it’s only for Leopard systems and it’s only for 64bit machines. My Mac Pro is 64bit and Leopard, but my iBook is 32bit and can’t run Leopard. And what about the tons of other developers out there who don’t meet these requirements? I can’t think of a good reason you have restricted Java 6 in this way, but I can think of a few bad reasons. Probably the easiest to come up with is that you’re trying to force Java developers to buy more expensive Apple machines.

What’s really funny about the crappy state of Java on the Mac is comments from Sir Steve himself, several years ago. I was at JavaOne in 2000. Sir Steve was the Mystery Date™ for the keynote speech on Day One of the conference. His Steveness trots on stage, clad all in black, and proclaims that he was going to make the Mac the ultimate platform for Java developers. Apple would be bundling Java 2 SE with OSX. And the crowd went wild. And he did make the Mac a great Java development platform. For a while. I can’t tell you how many conferences I went to after that, Java conferences, where the majority of developers were toting Mac laptops around. 

But then you started falling behind with the releases. And then you started restricting which of your users were worthy of getting updates. What gives, Apple? If Sun can release timely versions of Java that run on a ton of disparate systems, why can’t you release timely versions that run across your own hardware family? It’s absurd that you are only supporting 64bit Leopard system for the latest versions of Java, and even then you make us wait forever. 

So, how can we fix this? I think you should go back to Sun and say something like,

I’m sorry, Sun. We like to meticulously control everything, but in this case, that desire has caused us to hose down our customers. They’re not happy, and we can’t figure out a good way to appease them. Please, Sun, would you take over maintenance of the JDK/JRE for OSX? We’d really appreciate it.

Or something like that. Something needs to happen soon. Although the lastest version sounds like just another update to Java6, there are actually lots of new features that are going to really improve Java. Except those of us on the Mac have to wait for some unknown amount of time before you guys release your own version. And if we’re not 64bit Leopard, we’re screwed.

Please, Apple, help us out with some timely Java love, OK?

Sincerely,

Joey Gibson

Share and Enjoy:

  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • E-mail this story to a friend!

Groovy Sql Closure Examples

My post about closures last week generated quite a bit of traffic and comments, both positive and negative. I decided to followup on that post with a few examples of how to add a method that I believe is missing from Groovy’s Sql class that will execute a closure, and will guarantee that the connection gets closed, no matter the outcome of the closure’s contents.

I’m going to discuss three ways to add a method that does what we want:

  1. Wrap the existing class
  2. Modify the MetaClass of the existing class
  3. Use a Category

All three of these are extremely simple. I think it mostly comes down to preference as to which one you might want to use. Before we get started, let me say that Groovy is optionally-typed. What this means is that you don’t have to declare variable types if you don’t want to. I like not having to declare variable types, so I have not done so in any of these example. You might hate that, and think it sloppy/heretical/evil. If so, and you choose to use any of the code I present, feel free to declare your variable types. So, with that out of the way, let’s start with the wrapping approach.

Wrap the existing class

First, we’ll create a class called ISql that wraps an instance of Sql.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import groovy.sql.Sql
 
public class ISql
{
   public static newInstance(url, user, pass, driver, closure)
   {
     def con
 
     try
     {
       con = Sql.newInstance(url, user, pass, driver)
 
       if (closure)
       {
         closure.call(con)
       }
     }
     finally
     {
       con.close()
     }
   }
}

You can see that we’ve got a class with a single static method called newInstance, to mimic the standard way of creating a Sql instance. It takes the same four arguments that the Sql class does, but it takes one extra argument: a Closure. All this method does is create an instance of Sql, executes the closure, passing in the Sql instance, and then ensures that the connection gets closed, through the call to con.close() in the finally block. To use this class, you can do this

1
2
3
4
5
ISql.newInstance(url, user, pass, driver) {con ->
  con.eachRow("select * from Foo") {row ->
    println "ID: $row.id"
  }
}

In this test, we call our special newInstance method, passing in the connection parameters, and then tacking on a closure at the end. Inside the closure, we get access to the connection through the con variable, and then we can do anything we would normally do with a Sql connection. In this case, we execute a query and print the value of each row’s Id column. Nothing too exciting, but it works. No matter what happens inside those closures, the connection is guaranteed to be closed at the end. 

Modify the MetaClass of the existing class

The second way to do this is to add a method to Groovy’s built-in Sql class by modifying its MetaClass. Here’s the code to do that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Sql.metaClass.static.newInstance << {url, user, pass, driver, closure ->
  def con
 
  try
  {
    con = Sql.newInstance(url, user, pass, driver)
 
    if (closure)
    {
      closure.call(con)
    }
  }
  finally
  {
    con.close()
  }
}

Everything after line three is exactly like what we did in the wrapping approach. The magic occurs in line one. In that line, we get the Sql class’ MetaClass, and then grab the static property of the MetaClass. We then add another method called newInstance by using the << operator to append a closure taking the right number of arguments. To call it, we have code that looks almost identical to our last example, but instead of using the ISql class, we’re using Groovy’s built-in Sql class with our special method included.

1
2
3
4
5
Sql.newInstance(url, user, pass, driver) {con ->
  con.eachRow("select * from Foo") {row ->
    println "ID: $row.id"
  }
}

You can see that with the exception of the missing ‘I’, the code is exactly the same.

Use a Category

Groovy also provides something called Categories that allow you to add methods to existing classes, but they are only usable while the Category is in use. It’s somewhat confusing, and is my least favorite approach, but here’s how it works. You create a class with a static method taking the arguments you want to pass, plus an extra argument, usually called “self”, that will get passed the thing on which you’re calling this method. This special required argument must be the first in the list. Here’s our category called SqlHelper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import groovy.sql.Sql
 
public class SqlHelper
{
  def static newInstance(self, url, user, pass, driver, closure)
  {
    def con
 
    try
    {
      con = Sql.newInstance(url, user, pass, driver)
 
      if (closure)
      {
        closure.call(con)
      }
    }
    finally
    {
      con.close()
    }     
  }
}

Notice that the first parameter to newInstance is that special “self” variable. If you don’t include that argument in the method declaration, calling the method won’t work. I should add that you don’t actually pass any argument for “self” yourself when calling the method. This is handled by Groovy, in much the same way Python programs stuff values into a method’s “self” argument. So, to use the category, you have to wrap your operation in a “use” block

1
2
3
4
5
6
7
8
use(SqlHelper)
{
  Sql.newInstance(url, user, pass, driver) {con ->
    con.eachRow("select * from Foo") {row ->
      println "ID: $row.id"
    }
  }
}

Here, we declare that we want to use SqlHelper by using a “use” block that contains the category in parentheses. Within the curly brackets of the use (also a closure), Groovy will see our call to newInstance on the Sql class, and will figure out that we want to use the one in the category. It will then call that method, passing the Sql class as the self parameter, and all our other arguments as you would expect. With the exception of having to use the “use” block, this code looks just like the second example.

When Something Goes Wrong

I said that in each case, no matter what happens in the closure, the connection was guaranteed to get closed. Someone commented on the last post that he was concerned that the use of closures would somehow obscure where the problem occurred. It doesn’t. You still get the line number of where things went pear-shaped. For example,

35
36
37
38
39
40
41
42
43
44
45
46
try
{
  ISql.newInstance(url, user, pass, driver) {con ->
    con.eachRow("select * from boingo") {row ->
      println "ID: $row.id"
    }
  }
}
catch (Exception e)
{
  e.printStackTrace()
}

In this case, there is no table called “boingo,” and so when I execute this code I get an exception thrown, and from the stack trace, I can see where the problem occurred:

java.sql.SQLException: Invalid object name 'boingo'.
  ...
  at groovy.sql.Sql.eachRow(Sql.java:559)
  at groovy.sql.Sql.eachRow(Sql.java:541)
  ...
  at ISqlTest$_testBadness_closure2.doCall(ISqlTest.groovy:38)

I cut some of the stack dump out for brevity, but you can see that it was a java.sql.SQLException that was thrown, and it references line 38 in the code. That just as much information as you’d get from straight Java in this case, so you should be able to diagnose the problem.

Other Approaches

I should add that you should be able to subclass the Sql class, adding a static method called newInstance that accepts a closure in addition to the four connection arguments. I tried that, but it didn’t work. Actually, it partially worked. The newInstance method I added worked like a champ, but the original newInstance method was no longer visible. I don’t know why, but that’s the behavior I was seeing. It might just be that I’m not familiar enough with Groovy, but I couldn’t get it to work. If anyone knows why, let me know.

To Sum Up

So,