Older blog entries for cwinters (starting at number 6)

Well, the framework has been up and running as CGI on NT. It's just such a waste that it makes my spine cringe every time I think about it. Oh well. At least when they start doing some real work on that machine, we have an upgrade path for them (PerlEx to the rescue!).

Finally figured out what I think is a decent error reporting scheme between SPOPS and the framework. Before, SPOPS would die with a hashref with various pieces of information inside it. All fine and good, and sets things up for in the future calling die with an object instead (Alzabo has stuff setup like this, altho I don't know how well it works.)

However, the problem comes when you've got a eval {} wrapped around something that could be setting $@ to either a hashref or the normal string. Uh oh. Fortunately, the mod_perl guide comes to the rescue, courtesy of the ever-present Matt Sergeant. In it you see how to override the CORE::die function in perl and wrap your own. Neat, I thought, just check to see if $@ is a hashref and if not, put it inside one. Then everything checking the results of an eval {} can expect a hashref.

Of course, silly me forgets about the various CPAN modules being used. They certainly can't be expected to check whether $@ is a hashref or not. It's possible to overload the stringify 'operator' so that evaluating $@ (the hashref) in a scalar context actually returns what's in $@->{error}. But that's a little too much mucking about in the base expected behavior for me, particularly for something I'd like other people to use :)

So, I'm simply going to have all the SPOPS classes and objects set error information in a common package which anyone can inspect as needed. And on an error, they'll die with a simple scalar. And everyone will be happy.

Lesson learned: keep simple things simple.

Egads. Trying to port the framework not only to work under CGI, but also to run on NT. What braindead IIS engineer decided to tie STDERR to STDOUT? Unless you create a $SIG{__WARN__} handler, all warn() and carp() (etc.) calls are put out to the browser! And if you don't print out the header first, the browser will either ask if you can download the page or simply refuse to show it. What a pain.

I will be so happy when mod_perl works on NT without the current request serialization hassle.

Lots of traveling last week to visit and for a wedding. Driving 17 hours to florida (and 23 or so more successive hours in the next few days) wasn't as bad as I thought :) And it was actually nice to get away from email (etc.) for a few days. Although it was a little difficult to get back into the swing...

yapc was, of course, excellent. I don't know how Damian Conway ever gets to sleep with all those smarts running around in his head. Rusty posted a story about the quantum stuff which gives better details about it. One of the interesting side-effects of hearing him talk is that whenever I read his Object Oriented Perl book or any of the voluminous documentation his modules provide, I'll have an Australian voice running around my head...

Another cool thing was meeting some folks who are doing somewhat similar object persistence stuff. Schwern's talk on Class::DBI was interesting, and I think I'm going to swipe a few ideas from it -- with proper attribution of course :) Having something akin to 'stored procedures in perl' is very nifty.

The discussion after the talk was also useful. I learned that nobody else seems to be tying security to object persistence, so maybe there's hope for me yet :)

Orwant's talk this year was somewhat cryptic, despite the fact that I felt smug when he mentioned Temple Grandin and I actually knew who she was. He seemed to be discussing all the difficulties regarding copyright in a roundabout way, which might be the only method you can discuss it with an auditorium full of open-source geeks.

Maybe it was me, but I detected an undercurrent of concern regarding the upper levels of perl and the divisiveness found on p5p. Questions like: where is this coming from? Is this inevitable when a community grows? I'm not sure these are answerable questions, but Larry seemed to accept some of the blame when he said in his talk that he'd been working on the new Camel book for the last six months and hadn't had time to play his shepherd role. He also said that people need to argue about what they're arguing about, not bringing all the baggage into every argument. (He also said this is a Good Thing for a marriage too, and being almost three-months married now, I agree.)

But that's just me on the outside looking in, so it's probably wrong.

SPOPS are fairly settled now, security and all. And the web application framework is coming along very nicely as well. I hope to get it implemented on my website soon (next week), but these things have a way of not working out.

Side note: how the heck to people come up with clever names for projects? Right now the framework is just "the framework", or sometimes "Interact Application Framework." (IAF isn't bad, because then the programmers can be the "Interact Application Force".) But it seems like you either think of something clever early (I like the name of Jellybean) or not at all.... Or maybe it's just me :)

Anyway: the framework. Basically, a lot of the admin crap that is assumed to be in a framework -- users, groups, templating schemes, error handling, themes and a consistent output scheme -- is working and working solidly. Security on a per-object and a task basis is also working ok. (Don't know how it will scale, but...) Creating content handlers is a fairly simple process, and enabling security in a content handler is a matter of putting a certain class in your @ISA and setting a minimum security level for each publically accessible method.

Caching works, but not in as nice a fashion I'd like. And some things can almost certainly be tightened -- that's what happens when only one person works on the code. (Oh, did I mention that punk Rusty is leaving us to go to OpenSales?) ("Punk" in the nicest sense of course :) For caching, it would probably be a good idea to look into how Mason does it. I believe that everything is a component, and the parent Mason::Component class takes care of caching. The only wrinkle in this is, of course, themes. And you don't want to cache something that has any specific distinguishing items in it -- error messages, for example :)

I had a chuckle yesterday when I typed in the wrong password for monster.com -- I got a totally blank screen except for "You typed in the wrong password. Please try again." in big letters at the top. They're running superbowl commericials and I've got better error handling!

Really looking forward to yapc again this year. Except this year I don't have to be all worried about my presentation :)

Collections are now known as SPOPS, or Simple Perl Object Persistence with Security. (Although I'm working on the security right now :)

SPOPS aims to be storage-mechanism independent, although almost all of the work so far has been done with the DBI backend. (I've used both Sybase and MySQL with it, and porting it to a different db should be pretty easy, as long as they support a the $sth->{TYPE} and {NAME} interface and you can reasonably abstract out an ID-generation mechanism. (Sequences, for instance, should not be a problem at all.)) I'm hoping to implement the User/Group stuff not only using the DBI interface but also LDAP, which would be neat-o. (It would also likely expose some subconscious design decisions influenced by my RDBMS mentality...)

They're now fairly well extricated from the other projects that were using them, which should make it easier for me to consolidate the three or four versions that are floating around my ~/work directory. I think I'm going to upgrade my website to use them later on today so I can test out the user/group stuff.

They are also much easier to use now, thanks to Rusty's prodding. Instead of forcing you to use get/set accessor methods for an object, the data are now in a tied hash, so you can simply do: $user->{first_name} = 'Chris' to set information and then do $user->save; to save the user object. No context switching, and using a tied hash means that you can interpolate the values into strings (or templates...) without a second thought. Cool.

You can nab them, along with a working-and-rapidly-developing banner ad management system that uses them (called AdHomonym), at the AdHomonym website. I'm not quite ready to put them up on CPAN yet. Once I get an LDAP interface written and reasonably tested (or maybe re-port the interface to GDBM files from a six-month old project), then I'll feel decent about it.

Anyway, demos of the ad system coming soon.

Okay, so how do collections work? Here's an example:

my $user = $R->user->fetch( $uid );
print "Username: ", $user->username, "\n";
$user->set( 'first_name', 'Ding' );
$user->set( 'last_name', 'Dong' );
my $rv = $user->save();
if ( ! $rv ) {
  $R->error->add( 513, "Cannot add user record!" );
}
...
# Find all the user objects where the user's last name
# begins with w my $user_list = $R->user->fetch_group( where => "last_name like 'w%'" );
foreach my $user ( @{ $user_list } ) {
  print "Username: ", $user->username, "\n";
  print "Full Name: ", $user->full_name, "\n";
}

And so on. These are obviously really simplistic examples. But the idea is there. The variable $R is an object that acts as a container for other objects that live throughout the life of an http request -- much like the variable commonly called $r that is the first argument to any mod_perl handler.

Generally, there's a DBI database handle ($R->db), a server-wide configuration object ($R->config), the apache server rec object in perl ($R->apache), and a CGI object ($R->cgi). I've subclassed the base $R object to provide class aliasing as well. This way, I can call: $R->user which simply returns a class name (e.g., Intes::User) that can then be used to call an actual class method (e.g., $R->user->fetch( $uid ) becomes Intes::User->fetch( $uid )).

I'll try to get some basic stuff up on my website soon, depending on what Rusty winds up saying... :)

Like Rusty mentioned, we've been working a lot on Collections in perl. I probably picked the wrong term to use when I started writing them a number of months ago, because I think collection has some computer science baggage attached to it. It might be good baggage, I'm not sure. But since I don't remember enough of my CS classes to even be dangerous...

Anyway, a Collection is an object that represents some thing: a person who uses a website, a term in a dictionary, a translation between terms of two different languages in a dictionary, a relation between two terms in a dictionary (you can tell where I've been doing a lot of work recently). And the base Collection classes (currently two: Collection and Collection::DBI) don't make any assumptions about what the thing is. Collections basically just serialize (and cache) objects for later use. And generally the implementation classes are fairly simple, in the easiest case just defining some configuration information (database information such as fields, field types, table name, etc) and that's it. The interface for calling one collection object from another is fairly simple and you can build some fairly complicated relationships in this manner.

That it for now, more later.

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!