Pretty URLs

  • Mar 21, 2011

Way back when I wrote my own blog back-end, I went out of my way to make decent-looking URLs that didn't betray the use of PHP for the code. It's not that using PHP was inherently bad, but the ".php" in the URLs was ugly and would have made it tough to move to any other back-ends. It's just one of those good-idea cleanliness things. Back then, I did it with Apache MultiViews and just had names like "archive.php", so I could make URLs like "/archive/2002/12" for that month's posts.

Since I've started using Domino, however, it's gotten a bit tougher. The parts of the URL within a Notes database can actually be pretty great - something like "/People/Foo+Fooson" is about as good as you'd want. However, it's the database path that kills me. You can set up URL substitution rules, but that's a weird combination of setting up a Directory Web Rule plus making sure that every place you make a URL in your code uses that name. For something like a view column, that'd mean either hard-coding your server-specific setting or sucking it up and using @WebDbName. For the most part, I've given up and gone with the latter, for the sake of portability.

XPages bring good news and bad news.

The good news: your application almost never needs to care about the database file path, ".nsf" extensions, or anything of the like. There may be edge cases where you do, but for the most part you can just start your URLs with "/" and the database path is filled in for you (at the cost of starting non-DB paths with "/.ibmxspres/domino").

The bad news: even though the database path reference is now handled by the runtime and not the programmer's code, I don't know of a way to override the behavior. I'm sure it's there SOMEWHERE, buried in the hordes of Java classes and method calls spawned for each page request, but I don't see it. What I'd really want is to tell the XPages runtime that, while "/wow/forums.nsf" is the "right" way to reference the database, I'd rather it just start with something like "/forums". It seems like something that must be handled in the xsp.properties file, but I haven't found anything about it yet. Admittedly, it's tough to search for - most pages with the keywords I want are talking about @WebDbName replacements in SSJS and how to references external Domino resources. If it's not present already, maybe it's something they'll add in a future point release. One can hope.

Not much to look at

  • Mar 17, 2011

So I finally wrote a proper Cocoa app to accomplish a specific task! Here it is:

Ok, so its lack of actual UI makes it somewhat unimpressive. The "specific task" part is true, though. After running across a bunch of old AIM chat logs from various sources in my recent hard-drive-trawling, I decided to put them all in a DB for no discernable benefit, because that's the sort of thing I do in my spare time.

The AIM+ and two styles of gaim chats were easy, and I expect the Adium ones to be not too bad, but iChat gave me a little trouble. It's apparently used two formats over time, both of white are Apple-proprietary formats. I decided to focus on the older format, since most of the chat logs were circa-2002/2003.

After doing a little digging, I found that the files are in the format used by NSArchiver and NSUnarchiver, which appear to be the Cocoa method of object serialization. I pointed an NSUnarchiver at one of the chats and... it complained about not having the InstantMessage class. Fair enough.  After finding that Apple's InstantMessage framework is just meant for looking at your buddy list and doing AV stuff and not parsing logs, I grabbed the source of the horrifically-named chat browser Logorrhea. After I plunked its iChat data type classes into my project, all was well.

I found that the files consist of an NSArray (well, NSCFArray) with a mix of children representing chat attributes and the chat lines itself. I looped through that, checked the class of each one, and dealt with each appropriately. "Appropriately" in this case meant "converting to XML", so the agents in my database could read it back in properly. I haven't yet taken a whack at converting the body text from an NSAttributedString to HTML, so for now it's just the plain-text version.

It's rickety and I'm sure I did tons of stuff wrong, but it works! I ended up with a folder full of XML versions of the chats, ready to be imported next to the other logs. There's not much better to get your feet wet with a new environment than a clearly-defined basic task, I say.

For the morbidly curious, the pertinent code is here:

UnarchiverAppDelegate.h

UnarchiverAppDelegate.m

Television Man

  • Mar 10, 2011

A couple months ago, I set out to cut down as many expenses as I could, and my Comcast bill stuck out like a sore thumb. Thanks to a couple weeks of daily five-minute outages, I had already been switching over to (similarly-priced) FiOS service, but my TV service remained. Not only is cable service with a DVR, reasonable channels, and good HD coverage an expensive proposition regardless, what really gnawed at me was how ludicrously out of proportion the cost was to the actual use I got from it. TV service was about twice as much as my Internet service, but, whereas I use the Internet just about 100% of the time, I only watch a couple hours of TV a week... most of which is available from those channels for free online.

One option was to switch from Comcast TV over to Verizon. It'd be cheaper for a while, but I have no illusions that Verizon wouldn't creep up the price over time as new-customer deals start to wear off, and even if they didn't, the price/usage mismatch would remain.

So I set out to tackle the nigh-insurmountable problem of successfully replacing cable service with a computer with a good net connection. I had a circa-2007 Mac mini laying around that fit the bill nicely, so I cleaned off the old Leopard Server installation and got to setting it up. There are a couple things that make replicating a good TV setup such a sticky wicket:

  1. Many shows have their own, usually-crappy delivery mechanism. Some of them, conveniently, use Hulu, but some aren't even readily available at all.
  2. Even when shows ARE available, the image quality is pretty much universally far inferior to real HD TV shows.
  3. Much like replacing radio with an iPod, it's tougher to discover new shows without seeking them out. Fortunately, this isn't a huge problem.
  4. Media center apps, while impressive, tend to have at least one crucial flaw that undermines their utility.

The first two problems have necessitated a step into questionable morality and technical complexity. Namely, I set up an RSS reader to pull torrent files for new TV shows in pretty-much-HD quality, then a torrent client to download them, categorize them by name, seed to 200%, and then stop the torrent. I still don't have EVERY show we used to watch, but I have the big ones, and they're in pretty solid quality.

The last one is an ongoing project. I started out using Plex, which is pretty great and edges out the competition with some Mac-specific support. However, its YouTube plugin is pretty lacking and I'd rather not resort (yet) to learning Python and writing my own. I've switched over to its progenitor XBMC for now, which has a pretty solid YouTube plugin, but took a step back on other video sources. I'm considering setting up a Windows partition on the thing to see how the options are on the other side (like MediaPortal), but I'd rather avoid having to do that.

Overall, my TV experiment has worked out pretty well, but it's primarily due to my specific situation. If normal TV was a bigger deal in the apartment (say, if we had kids), this would be a woefully inadequate replacement. Similarly, if I didn't enjoy doing crap like setting up RSS feeds for torrent processing or manually managing TV-show libraries and video-output settings, it'd be too much hassle to be worth it. And I certainly don't miss the Comcast bills.

What's next?

  • Mar 6, 2011

Thanks to The Brads, I ran across Dribbble the other day, and it's the new coolest thing ever. The two main things that struck me were "man, modern web designs use a LOT of soft gradients" and "hmm, I really want to make some more web sites now." The latter is pretty much the point.

I've never been a web designer. With enough effort, I can sort of emulate one, but the results are expectedly mediocre. That's mainly because that's a natural extension of being a web developer - the stuff I program has to look like something, and CSS is essentially a programmer's design tool anyway. However, visual design isn't my gig, so I don't feel the least bit squeamish about cobbling together something reasonably clean and aesthetically pleasing from various sources of "inspiration" and calling it a day.

Fortunately, looking at nice, clean designs (like this WordPress admin site, actually, which I kind of like) is good inspiration nonetheless, since it makes me want to write something cool enough to rise to the occasion. A minimalist design with exaggerated tabs, labels, and such implies that the stuff you're looking at is organized logically enough to match, and that's the kind of thing I can do.

Now that GCD is a reasonable 1.0, Dribbble has me itching to move on to what's next. Far and away the best candidates for fancy new UIs are my various projects for work, but that's only ever so exciting. Maybe I'll take another pass at my Minecraft server to see if I can take advantage of its database-attached-ness. Probably better would be really diving into Cocoa programming - that'd be fun AND potentially directly useful for future job prospects. Heck, it'd even be good for my CURRENT job, since having a proper iPhone UI is on our list of big to-dos. Hmm, yep, that's what I'll do.

Displaying mixed-type Rich Text in an XPages repeat control

  • Mar 3, 2011

I'm not sure if "mixed-type" is the right term for what I mean, but it should do.

A couple months ago, I ran into a problem where I wanted to display the posts in a forum topic on an XPage, which isn't a terribly complicated thing to do. However, I ran into a bit of trouble in how, specifically, to go from the <xp:dominoView/>  data source to proper rendering of the rich text for each post, in part because some posts were MIME data and some were the native Notes rich text format. The rich text naturally wasn't in a column value, so I couldn't just refer to the column by name using the var name int he <xp:repeat/>.

I wrangled with this for a little while, writing JavaScript code to check if it's in MIME or native format, but I kept running into problems with how to convert the rich text data on the fly. I didn't want to just lose all the rich text formatting by using NotesItem.getUnformatetdText() or an equivalent, but I couldn't just return a NotesItem object to the <xp:text/> control. I knew that XPages know how to convert it, since they do it just fine if you're working with a NotesXspDocument, so I wanted some way to access that functionality.

<xp:panel/> came to my rescue. Within the <xp:repeat/>, I created an <xp:panel/> with its own data section containing an <xp:dominoDocument/> with its documentId property set to the UNID of the view entry I was currently working with. Then, I could just create an <xp:text value="#{doc.Body}"/> and let the renderer take care of all the details.

For all I know, that was an extraordinarily inefficient way to do it, server-wise, but it may be the cleanest way to do it from the programmer's perspective.