CFGroovy in Forty Lines

It's been a couple months since I've done anything with CFGroovy.  I've been mulling how to get back to the essence, which is Groovy scriptlets in CFML.  Today at cf.objective() I put my fingers back on the keyboard for the first time.  Here's a full implementation of the tag in 40 lines.  There are no bells and whistles, and no Hibernate support, just scriptlets.  But it's production worthy.



  
  
  
  
    
  
  
    
  
  
  
  
  
    
  
  
    
  
  
  


  
    
    
  

  
  
  
    
  
  
  
  

It does depend on having Groovy already available on your classpath (one of those missing bells and whistles is auto-loading Groovy).  This is the first version of the CFGroovy 2 line, which I've decided will be a ground-up rewrite.  Backwards compatibility is a goal, and I think it's a reasonable one, but where CFGroovy 1.0 was developed with an application focus, CFGroovy 2.0 will be developed with an architecture focus.  If you liked this write-up and you would like to acquire far more information https://climatex.org/exxonmobilerewardsplus/ to find out more. I'm willing to sacrifice a little backwards compatibility, particularly with Hibernate integration, to attain that.

Random ColdSpring Weirdness

Just had a totally random thing happen with ColdSpring.  I'm a big fan of the use-advice-as-advisor shortcut when you want to proxy every method on a bean.  I use it all over the place.  Tonight, however, it completely failed.  No idea why.  This app (PotD) has been running with the same version of ColdSpring for quite some time, all with out issue.  I reloaded the app tonight to test a change, and it bombed trying to find the "matches" method on my Advice.  Reverted my change, reloaded again, same issue.  Restarted ColdFusion and still the same.

The fix was simple.  Where I used to have this:

<bean id="transactionAdvice" class="sorter.cfcs.transactionadvice" />

I now have this:

<bean id="transactionAdvice" class="coldspring.aop.support.NamedMethodPointcutAdvisor">
  <property name="advice"><bean class="sorter.cfcs.transactionadvice" /></property>
  <property name="mappedNames"><value>*</value></property>
</bean>

Problem solved by being explicit, though it'd be nice not to have that extra XML in there since ColdSpring is supposed to infer it automatically.  Oh well.  And yes, that's the wrong id for the Advisor bean, but in the interest of getting the app back online, I just used the same name so all my proxy configurations wouldn't have to be updated.  I'll go back and fix it at some point.

Das "Most Disappointing" Keyboard

Das KeyboardAs you probably know, I got a Das Keyboard a little while ago, because my previous keyboard, which I liked very much, started getting a couple sticky keys.  I'll freely admit I'm a keyboard snob, but I don't think it's terribly unreasonable given how much time I spend typing.  Unfortunately, Das Keyboard has proven to be a complete piece of junk.

The action is great, the keyboard is attractive, it's heavy (no sliding).  It's on the loud side, no question, but it's not terrible.

However, it doesn't type in the right order.  There is some sort of bug in it's internal scanning that causes nearly-simultaneous keypresses to always be returned in a left-to-right order, regardless of what order they were actually pressed.  And it's not a "sometimes" thing, it's perfectly repeatable.

When I first got the keyboard, I immediately noticed that I typed poorly with it.  I didn't think much of it, since the action is quite a bit different than my last one, so I figured I just needed to get used to it.  After a couple weeks, however, I wasn't improving, and I started to notice certain patterns in my errors.   After a bit more observation, I realized that the errors were all related to the spatial orientation of the offending keys.

For example, the word "keyboard" has the pairs "ke" and "oa" within it.  These pairs are special because they are each typed with one finger from each hand.  As such, it's very easy to type the letters in very rapid succession, even if you're not a particularly speedy typist.  Further, you'll notice the right hand goes first.

The most damning example of this, of course, is the "he", in the word "the".  A close second is BACKSPACE and any printable character.  In this case, rather than reversing the letters, the printable character gets scanned first (all characters are left of the BACKSPACE), and then the BACKSPACE immediately deletes it, leaving the original erroneous character intact.

Keyboard Test ToolBeing a fan of science, I wanted to demonstrate this more objectively.  To remove the human factor (at least most of it), I made a little test tool composed of two pencils strapped together with a pocket knife as a spacer.  It puts the erasers exactly a key-width apart, so they'll press down neighboring keys.  More importantly, one pencil is slightly higher than the other, so while they'll press down two keys, one key will be pressed slightly earlier than the other.

Using this tool, aligning the "leading" pencil over the 'a', and the "trailing" pencil over the 's', a series of drops will look like this (taken with the tool, directly into the WordPress editor):

asasasasasasasasas

After flipping the pencil so the 's' key has the "leading" pencil, a series of drops looks like this (also taken directly into WordPress):

asasasasasasasas

As you can see, they are exactly the same! 'a' always preceeds 's', regardless of which order they are pressed in, as long as the separation between the two presses is small enough.  This behaviour is not unique to the 'a' and 's' keys; it happens all over the keyboard, as long as the second letter key is to the left of the first key.

Manually retarding the drop so that the key presses have a larger delay between them results in correct behaviour, as expected.

Needless to say, I'm very disappointed in this supposedly "ultimate" keyboard.

NaturallyCarolicious.com Is Live

One of my WordPress projects was helping a friend move her blog from TypePad over to a self-hosted WordPress with a shiny new domain name: naturallycarolicious.com.  As of today she's made the official "welcome" post, and the new site is running like a champ.  She's still some design stuff, but that's just icing on the cake.

Biggest problem was that she was using a TypePad subdomain instead of a custom domain, which precluded any sort of transparent switch-over via DNS.  TypePad also doesn't have a half-way between drag'n'drop themes and roll-your-own, which meant that changing the site header to include a redirect was out.  So I had to resort to JS, which is hardly elegant, but it works well enough.  I was really hoping for .htaccess support, but pushing one up there had no effect, so they don't have it enabled in their Apache (or whatever) config.  Oh well.  Unfortunately this means search engines have to organically rebuild their indexes (since I can't give them a 301), but a robots.txt will at least ensure the old stuff drops out.

Once all that was sorted, however, things went pretty smoothly.  Found a great WordPress plugin for doing search and replace within your content, which made updating internal links a breeze.  It also happens to output search results in a fashion that was really easy to rip with jQuery into a list of files (pics, movies, etc) to grab with wget and then bulk upload into WordPress.  And let me tell you, bulk uploading into WordPress is kickass; Flash for the win!

Did a little minor theme work, changed permalinks to only use year/month/slug (to match TypePad), and that's about it.  Smooth as butter.

Welcome home, Carole.

Happy Mother's Day

Happy Mother's Day to all you mothers out there.  In particular:

  • Barney and Peggy's mother

All these mothers too, of course:

  • Lindsay and Emery's mother
  • Richard, Thomas, Robert, Dorothy, Dolores, and Carolyn's mother
  • Susan, Thomas, Gerald, and Renee's late mother
  • Nikolai and Gabriel's mother
  • Adelaide's late mother
  • Adalina and Matteo's mother
  • Christopher, Moira, Iain, and Michaela's mother
  • Teresa, Matthew, Anthony, and Maggie's mother
  • Sally and Marie's mother
  • Sarah, John, and Jenny's mother
  • Ana's mother
  • Ayden and Owen's mother
  • Michael and Jenna's mother
  • Lucy's mother

As for the other couple billion mothers out there (some of whom undoubtedly should have been on that list), Happy Mother's Day to you too.

The Kember Identity Hash

A few days ago I saw a tweet from Steve Withington about the Kember Identity Hash.  I whipped up a searcher in Groovy, just for the hell of it, and have been running it for the past couple days on my office machine when I'm not using it.  Aside from the sheer pointlessness of the task, it's kind of interesting, and so tonight I entertained myself by doing a bit of a write up on it.

Actually was kind of fun.  That page serves as the "master" tracker for any running instances of my script, so I have a centralized location that tracks the number of hashes I've searched regardless of where they ran.  It renders the code (pulled from SVN, though it's cached for performance reasons).  It displays some progress information  It got me to finally commit my /r/ directory.  Most of all, it entertained me for a few hours, and had nothing to do with PHP or WordPress.  And if I get past that inch of progress (on my way to 33 billion light years), I might even win $100.

What the Hell is Wrong With Me?

For the past month or so I've written more PHP than every other language combined.  That's including English.  Really.  Four separate WordPress projects (two standalone, two MU), one of which is a blogging platform for Mentor Graphics, and I'm up to my neck.  I'm a CFML developer by profession; I think I got off at the wrong stop.

What I have learned?

  1. PHP's function libraries are insane.  I thought ColdFusion's (now CFML's) libraries had plenty of wonkiness, but PHP makes them look like the friggin' Pope.  Latest example: there is a 'sort' function that sorts an array.  It has an optional second parameter for controlling the type of sort.  But it's a whole separate function with identical parameters (called 'rsort') to sort descending.  Where's the optional third parameter for direction?  Or how implode accepts arguments in either order, but explode (it's inverse) does not.
  2. Dollar signs are harder to type than hashes.  Not sure why, especially with my big hands, but whatever.
  3. PHP's operators are lunacy.  Arrays are declared with "=>" for keys, by dereferenced with "['key']" syntax.  Object members are accessed with the "->" operator, and "." is for string concatenation.  And you can't combine the middle two in arbitrary ways (though some ways do work).
  4. WordPress was designed by really smart people.  A little too smart, I think.  And even aside from the choice of language, the code style confirms without a doubt that they're PHP developers to the bone.
  5. Implicit invocation is great, but while it fosters decoupling, overuse can create a developer's nightmare.  With too much indirection the code can't be easily read, so you have to simply memorize huge amounts of information in order to effectively work on an application.

Now before you go assuming I'm a PHP hater…

  1. I largely put myself in this situation.  I was in charge of selecting WordPress MU for Mentor's infrastructure, knowing I was brining PHP into an 85% CFML / 10% Groovy / 5% Java shop.  Five people (of nine) on the team swear by it for our personal blogs, though I was the only one with any substantial experience hacking the engine itself.  Despite initial reservations from the boss, and others (including myself), time has shown that it was clearly a good choice.
  2. PHP is friggin' fast.  Dear god is it fast.  With no concept of in-memory sharing across requests, everything has to reload on every request and it still screams.
  3. WordPress is a really flexible platform.  It's provides a solid foundation, a kickass application framework built atop it, and a great blogging engine on top of that.  And if you get the right theme(s), you've got presentation and CSS as well.  It's not a CMS out of the box, but for what it's designed to do it's fantastic.
  4. PHP's function types and higher order functions are kind of a mess, but at least they have them, and they support object methods.  You wouldn't believe how often this bites me in CFML.

Am I gonna drop CFML for PHP?  Hell no.  But despite PHP's and WordPress's warts, there's a lot of stuff worth of emulation.  Definitely reenforced my belief that CFML is an inherently iffy language for "down-n-dirty" development, even though it excels at templating and simplifying complex tasks.

On the surface, CFML is no where near as warty as PHP, but looking deeper and the story isn't so clear.  It seems like every couple weeks I discover or learn about some utterly bizarre behaviour that ColdFusion exhibits, and unlike PHP's weird function libraries, they're internal weirdnesses.  Functions can be stupid, but at least they're in your face.  You get a hard fail if you type one wrong.

Long post, and again, no real point.  Whatever.  It's Thursday, and better for my liver than drinking.

WordPress MU – No Longer a Bare-Domain Nazi

A week or three ago I learned that WordPress MU was explicitly coded to refuse to run on a 'www' subdomain, instead forcing you to run it on the bare domain.  While running your website on the bare domain is certainly a reasonable thing to do, forcing users of your software to do it seemed, well, idiotic.  I happen to think that the 'www' subdomain is the proper place to run your website, though since the bare domain is widely used, I ensure that if you visit 'barneyb.com' you'll have exactly the same experience as if you visit 'www.barneyb.com'.

Being the good (if opinionated and occasionally obnoxious) open source aficionado that I am, after my initial reaction of outrage, I've revisted the issue and "fixed" the problem.  Aside from the install script (index-install.php), there was only one place that needed changing (in wpmu-settings.php).  The patch is below, made against WordPress mU 2.7.1:

Index: index-install.php
===================================================================
--- index-install.php   (revision 5342)
+++ index-install.php   (revision 5343)
@@ -362,8 +362,6 @@
        $weblog_title = ucfirst( $_SERVER[ 'HTTP_HOST' ] ) . ' Blogs';
        $email = '';
        $hostname = $_SERVER[ 'HTTP_HOST' ];
-       if( substr( $_SERVER[ 'HTTP_HOST' ], 0, 4 ) == 'www.' )
-               $hostname = str_replace( "www.", "", $_SERVER[ 'HTTP_HOST' ] );
        ?>
        <form method='post' action='index.php'>
                <input type='hidden' name='action' value='step2' />
@@ -511,8 +509,6 @@
        global $wpdb;
        $domain =   $wpdb->escape( $_POST[ 'basedomain' ] );
        $domain = str_replace( 'http://', '', $domain );
-       if( substr( $domain, 0, 4 ) == 'www.' )
-               $domain = substr( $domain, 4 );
        if( strpos( $domain, '/' ) )
                $domain = substr( $domain, 0, strpos( $domain, '/' ) );
        return $domain;
@@ -649,12 +645,6 @@
 $action = isset($_POST[ 'action' ]) ? $_POST[ 'action' ] : null;
 switch($action) {
        case "step2":
-               if( substr( $_POST[ 'basedomain' ], 0, 4 ) == 'www.' ) {
-                       printheader();
-                       nowww();
-                       continue;
-               }
-
                // get blog username, create wp-config.php
                step2();

@@ -662,7 +652,6 @@
                include_once('./wp-config.php');
                include_once('./wp-admin/includes/upgrade.php');

-               $_SERVER[ 'HTTP_HOST' ] = str_replace( 'www.', '', $_SERVER[ 'HTTP_HOST' ] ); // normalise hostname - no www.
                make_db_current_silent();
                populate_options();
                global $base;
Index: wpmu-settings.php
===================================================================
--- wpmu-settings.php   (revision 5342)
+++ wpmu-settings.php   (revision 5343)
@@ -6,8 +6,6 @@
 $wpmuBaseTablePrefix = $table_prefix;

 $domain = addslashes( $_SERVER['HTTP_HOST'] );
-if( substr( $domain, 0, 4 ) == 'www.' )
-       $domain = substr( $domain, 4 );
 if( strpos( $domain, ':' ) ) {
        if( substr( $domain, -3 ) == ':80' ) {
                $domain = substr( $domain, 0, -3 );

Irish Tunes means Irish Whiskey

At least according to Pandora.  I've not noticed music-tuned ads before, so maybe it's just a coincidence, but interesting none the less.  Or I'm just drunk and wishing I'd gone to Lacuna Coil and Disturbed with certain other CF guys.

MySQL Tuning

While tuning my new server, I came across an article on  MySQL tuning that does a really great job of laying out the main options that need to be tweaked, as well as explaining what they do.  It's several years old, but still applicable.  Also worth mentioning that MySQL ships with four "sample" configuration files for small, medium, large, and huge servers.  The compiled-in defaults (at least with RedHat binaries) are somewhere around the "medium" server, which is for "systems up to 128M where MySQL is used together with other programs (such as a web server)".  To put that another way, if your hardware was built this century, the defaults are horribly conservative.

In particular, if you're using InnoDB, you simply must set 'innodb_flush_log_at_trx_commit' to either zero or two.  The default of one will kill you.  I've never picked two (for the data I collect that extra second of safety is irrelevant), but you might want to.