<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-5369352</id><updated>2009-07-01T19:38:16.401-07:00</updated><title type='text'>JD Tangney &amp; Associates</title><subtitle type='html'>Tips, tricks and discoveries we've made developing software - especially web-based apps - for kids and education.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jdtangney.com/blog/atom.xml'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default?start-index=26&amp;max-results=25'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>296</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5369352.post-4069705825017298683</id><published>2009-06-29T11:52:00.000-07:00</published><updated>2009-06-30T00:51:41.041-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>Unreliable Tomcat</title><content type='html'>Tomcat has had a memory leak for at least a decade that I am aware of. If you deploy by copying a war file to the webapps directory, sooner or later Tomcat runs out of memory. It's hard to kill tomcat when it's wedged in this way, since the standard way of shutting down is to send a request (via the shutdown script). If Tomcat is too ill to listen to requests, you can't shut it down. Usually the solution is to find its pid and kill it from the command line.

How to automate this? That is, I want to reboot tomcat automatically, even when it's wedged. It sure would be nice if there was a pid file...

Well, there can be a pid file. Set CATALINA_PID to the path to a pid file you want tomcat to use, and the catalina.sh script (called by startup.sh) will do the right thing. Then, in order to get shutdown.sh to make use of the pid file, simply stipulate -force.
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-4069705825017298683?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/4069705825017298683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=4069705825017298683' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/4069705825017298683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/4069705825017298683'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/06/unreliable-tomcat.html' title='Unreliable Tomcat'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-6440972150390396188</id><published>2009-06-17T23:44:00.001-07:00</published><updated>2009-06-17T23:44:51.414-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='regex'/><title type='text'>Eclipse Regular Expressions plugins</title><content type='html'>&lt;p&gt;Whenever I need to use regular expressions in Java, I end up wasting time messing with them to get them to work. And because you have to write your regex as a String in Java, you have to escape all the backslashes. Pretty soon, it becomes really hard to read. What I would really like is a plugin that lets me test my regex dynamically.&lt;/p&gt;
&lt;p&gt;Others have thought of this. So I installed a variety of them and tried them out.&lt;/p&gt;
&lt;p&gt;First up, &lt;a href="http://www.brosinski.com/regex/"&gt;Eclipse Regular Expression Tester&lt;/a&gt;. Its update site is http://brosinski.com/regex/update After installing, it shows itself in the preferences as RegEx Tester. It provides a new view called RegEx Tester. After a little testing, it seems that it does its job. The view makes very inefficient use of screen real estate. The results of the "test" occupy too much vertical space.&lt;/p&gt;
&lt;p&gt;I also did not like the way you have to configure regex parameters globally. When I'm doing regex stuff, it's different every time. I need to be able to tweak in a more immediate way.&lt;/p&gt;
&lt;p&gt;Next is &lt;a href="http://www.bastian-bergerhoff.com/eclipse/features/web/QuickREx/toc.html#installation"&gt;QuickREx&lt;/a&gt;. The update site is http://www.bastian-bergerhoff.com/eclipse/features&lt;/p&gt;
&lt;p&gt;This one does a variety of flavors of regex (JDK, ORO, blah, blah, with Perl and awk varieties) fwiw. You can also keep the regex's and "test text" in a library.&lt;/p&gt;
&lt;p&gt;This thing is even worse with screen real estate, but at least the options are available in the view so you don't have to go to the prefs to change them. There's also a dialog for constructing a regex by selecting components from dropdowns. This seems a little odd to me, since if you know the meanings of all the terms in the dropdowns, you almost certainly know a shitload about regex and you don't need this tool. Whatever.&lt;/p&gt;
&lt;p&gt;Anyway, it's the winner so far, even though the "copy regex to Java String" button doesn't work.&lt;/p&gt;
&lt;p&gt;On to &lt;a href="http://myregexp.com/eclipsePlugin.html"&gt;Regex Util&lt;/a&gt;. Update site is http://regex-util.sourceforge.net/update/ This is all about Java-style regex's, so maybe less UI clutter? Anyway, this one has no prefs. The UI is nicely laid out: minimal. Options and flags are dropdowns, not a gazillion checkboxes. Unlike the others, this one does not show groups, but it &lt;i&gt;does&lt;/i&gt; highlight the match as you select parts of the regex. This seems like a cool debugging tool. Besides, once can always go into "replace" mode and enter the requisite $1, $2 and so on.&lt;/p&gt;
&lt;p&gt;And copying to a Java-style String works &lt;i&gt;and&lt;/i&gt; the opposite function is available.&lt;/p&gt;
&lt;p&gt;Yay! This one is the winner.&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-6440972150390396188?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/6440972150390396188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=6440972150390396188' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/6440972150390396188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/6440972150390396188'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/06/eclipse-regular-expressions-plugins.html' title='Eclipse Regular Expressions plugins'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-254139713336337613</id><published>2009-06-13T22:15:00.001-07:00</published><updated>2009-06-13T22:15:12.367-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='macos'/><category scheme='http://www.blogger.com/atom/ns#' term='voip'/><title type='text'>Mumble or Skype?</title><content type='html'>&lt;p&gt;We use Skype a lot at &lt;a href="http://industriallogic.com"&gt;Industrial Logic&lt;/a&gt;. But we also use VNC, and if the person running the VNC server has a low upstream bandwidth, the voice quality is unusable. We thought we might give Mumble/Murmur a try.&lt;/p&gt;
&lt;p&gt;As it happens, I have done a bunch of research on VoIP technologies and speech codecs, so when I saw that Mumble uses &lt;a href="http://www.speex.org/"&gt;Speex&lt;/a&gt;, I knew that it is on the right footing.&lt;/p&gt;
&lt;p&gt;Two thing need to happen in order to get to the point where we can do some tests. The first is to set up the server. The Windows download of mumble includes murmur, and there are RPMs and static builds of murmur for Linux-based systems. As it happens, MacPorts has a murmur install, so on MacOS it's a simple matter of&lt;/p&gt;
&lt;blockquote&gt;
  &lt;pre&gt;
port install murmur
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Configuring the server — something I have yet to try — appears to be &lt;a href="http://mumble.sourceforge.net/Installing_Mumble#Post-installation_tips"&gt;documented&lt;/a&gt;, but the proof is in the pudding.&lt;/p&gt;
&lt;p&gt;Just for giggles, I fired up mumble in an attempt to connect to a public server. It seems that much of the goodness of mumble comes from it being configured correctly. In particular, it needs to be trained so that the background noise-filtering works correctly.&lt;/p&gt;
&lt;p&gt;I have not reached on conclusion on whether mumble can replace skype for my bandwidth-challenged brethren. If I get 'round to installing murmur, we can give it a try.&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-254139713336337613?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/254139713336337613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=254139713336337613' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/254139713336337613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/254139713336337613'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/06/mumble-or-skype.html' title='Mumble or Skype?'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-5960650774590799881</id><published>2009-06-13T21:55:00.001-07:00</published><updated>2009-06-14T19:15:30.735-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='macos'/><title type='text'>Notes on making a simple auth app using Wicket</title><content type='html'>&lt;p&gt;Follow the instructions &lt;a href="http://wicketstuff.org/confluence/display/STUFFWIKI/Wicket-Security"&gt;here&lt;/a&gt; and add the junk to your pom. You'll need to add a &lt;code&gt;repositories&lt;/code&gt; element in which to put you &lt;code&gt;repository&lt;/code&gt;. I put mine near the end, after the &lt;code&gt;build&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;mvn install&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I prefer JUnit 4 to 3.8, so I removed the generated "variable" ref from my class path and added Eclipse's built-in library for JUnit 4.&lt;/p&gt;
&lt;p&gt;To keep things consistent, I modified the pom to refer to JUnit 4.. Maybe I should have let the Eclipse build reference the Maven repo rather than Eclipse for its JUnit. Hmm.&lt;/p&gt;
&lt;p&gt;Added "variable" ref for both swarm and wasp (sheesh - why two? This is so confusing) and changed my application to extend &lt;code&gt;SwarmWebApplication&lt;/code&gt; as described in the &lt;a href="http://wicketstuff.org/confluence/display/STUFFWIKI/Getting+started+with+Swarm"&gt;swarm getting started doc&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course, Eclipse helped me out with the stubs of the overrides of the abstract methods, so on to filling them in.&lt;/p&gt;
&lt;p&gt;So, starting with a bare-bones app, start adding security. Hmm. Not working.&lt;/p&gt;
&lt;p&gt;OK, so start with the kitchen-sink security demo app and begin deleting unneeded code. Hard, because I don't have a project and have to rely on reconstructing one from the war.&lt;/p&gt;
&lt;p&gt;Aaargh! Give up on swarm. The guy's dead anyway, so who's maintaining it?&lt;/p&gt;
&lt;p&gt;So auth-roles is the next.&lt;/p&gt;Generate a project using mvn. Modify the pom to include auth-roles:&lt;br /&gt;
&lt;pre&gt;
&amp;lt;dependency&amp;gt;
&amp;lt;groupId&amp;gt;org.apache.wicket&amp;lt;/groupId&amp;gt;
&amp;lt;artifactId&amp;gt;wicket-auth-roles&amp;lt;/artifactId&amp;gt;
&amp;lt;version&amp;gt;1.4-rc4&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Then use &lt;code&gt;mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true&lt;/code&gt; to make the eclipse project. Import into eclipse.&lt;/p&gt;
&lt;p&gt;Copy gibblies from the "wicket-auth-roles-example" available on &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=119783&amp;amp;package_id=138752"&gt;Sourceforge&lt;/a&gt;. (It's in maven too if you know how to get it. I don't.) It has a weird structure, not like the autogenerated one with the embedded Jelly, so that's why we have to copy/paste.&lt;/p&gt;
&lt;p&gt;A couple little syntax errors: Stuff that's presumably changed in more recent releases. An overridden constructor needs to be deleted, since the thing it overrides no longer exists. Stuff like that.&lt;/p&gt;
&lt;p&gt;And the source needs to be reformatted. What's with all this C#-like source formatting anyway? Sheesh, this is Java, guys.&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-5960650774590799881?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/5960650774590799881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=5960650774590799881' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5960650774590799881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5960650774590799881'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/06/notes-on-making-simple-auth-app-using.html' title='Notes on making a simple auth app using Wicket'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-5543906304204223674</id><published>2009-06-13T21:54:00.001-07:00</published><updated>2009-06-13T21:54:35.875-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='macos'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP Again</title><content type='html'>&lt;p&gt;Since &lt;a href="/blog/2008_10_01_archive.html"&gt;my last post&lt;/a&gt; about PHP dev, Eclipse PDT seems to have matured a bit. So I am having a go at installing it.&lt;/p&gt;
&lt;p&gt;First, I uninstalled PHPEclipse and the xdebug plugins, and installed PDT. The instructions, mysteriously, are quite complex. Find them &lt;a href="http://wiki.eclipse.org/PDT/Installation"&gt;here&lt;/a&gt;.

&lt;/p&gt;
&lt;p&gt;I had a very frustrating time getting dependencies to resolve properly, until I found a hint somewhere that suggested that my Eclipse install was "messed up." So I downloaded a fresh Eclipse for J2EE and finally got PDT 2.0 installed.&lt;/p&gt;

&lt;p&gt;This came at the cost of all the gaziilion other plugins I had installed, like the Google App Engine support, Ruby and Python support and so on. Feh. I'll live. &lt;/p&gt;

&lt;p&gt;I disliked all the UI clutter introduced by the xdebug plugin so, contrary to Paul Scott's advice, I am giving zend debugger a whirl. 

&lt;p&gt;It seems that PDT comes with the "client" end of the Zend debugger, so all we need is the server. &lt;a href="http://www.thierryb.net/pdtwiki/index.php?title=Using_PDT_:_Installation_:_Installing_the_Zend_Debugger#Installing_Zend_Debugger_server"&gt;These instructions&lt;/a&gt; purport to guide one through that.&lt;/p&gt;

&lt;p&gt;Make a phpinfo.php file containing only &lt;code&gt;&lt;?php phpinfo(); ?&gt;&lt;/code&gt; and execute it to see what php thinks about itself and its world. &lt;/p&gt;

&lt;p&gt;Follow the instructions in the readme that comes with &lt;a href="http://downloads.zend.com/pdt/server-debugger/"&gt;the download&lt;/a&gt;. First, I copied ZendDebugger.so into /usr/local/lib. Then I made /etc/php.ini by copying the default found in the same directory. This is what I added:
&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;[Zend]
zend_extension=/usr/local/lib/ZendDebugger.so
zend_debugger.allow_hosts=127.0.0.1, 192.168.1.0/16
zend_debugger.expose_remotely=always&lt;/code&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;
&lt;p&gt;I was also told to copy dummy.php into your Apache docroot, but I don't know why. I put mine in &lt;code&gt;/Library/WebServer/Documents/&lt;/code&gt;

&lt;p&gt;To confirm that it's installed, we use our phpinfo.php and search for "debugger". There will be a reference next to the copyright as well as an entire section of zend debugger-related info.&lt;/p&gt;

&lt;p&gt;We need the client end of the debugger which is not provided by Eclipse for licensing reasons. Get it &lt;a href="http://downloads.zend.com/pdt/debugger/org.zend.php.debug_feature-I20081217.zip"&gt;here&lt;/a&gt;. (The referring page is &lt;a href="http://www.zend.com/community/pdt"&gt;here&lt;/a&gt;.) Hmmm. It seems you can get it from an &lt;a href="http://downloads.zend.com/pdt"&gt;Eclipse update site&lt;/a&gt; as well.

&lt;p&gt;Leopard comes without pear so we have to install it:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;
cd /usr/local
curl http://pear.php.net/go-pear &amp;gt; go-pear.php
sudo php -q go-pear.php
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note that the go-pear script is very fragile and pretty badly written. It is easily confused. Make sure you are in the directory you want it to install into (&lt;code&gt;/usr/local&lt;/code&gt; in our case), or it will get things horribly wrong. When it's done, it will have fixed your php include_path too. Use &lt;code&gt;pear config-show&lt;/code&gt; to see how it's been set up. &lt;/p&gt;

&lt;p&gt;Now, to install PHPUnit, all we need do is
&lt;blockquote&gt;
  &lt;pre&gt;
sudo pear channel-discover pear.phpunit.de
sudo pear install phpunit/PHPUnit
&lt;/pre&gt;
&lt;/blockquote&gt;

It turns out that PDT does not support running PHPUnit directly, so I created an "external" run configuration in Eclipse to make it happen.

[how? Maybe I'll fill in the details some time. Not now. It's my blog and I will write what I like.]

I can finally test-drive some code!

Next, deploy it. Zend Framework likes to assume it's at the root of your docroot, so people typically create a virtual host to make that happen.

I found that Zend Framework apps really want to see Zend on the include_path so we add it in php.ini. But first we put a copy of the framework in a central spot. I chose /usr/local. So the whole download lives in /usr/local/ZendFramework-1.8.1. We'll want a symlink to isolate us from version lockin, so inside /usr/local, I did a 

&lt;blockquote&gt;
  &lt;pre&gt;
ln -s ZendFramework-1.8.1 ZendFramework
&lt;/pre&gt;
&lt;/blockquote&gt;

Now my include_path looks like this:
&lt;blockquote&gt;
  &lt;pre&gt;
include_path=".:/usr/local/PEAR:/usr/local/ZendFramework/library"
&lt;/pre&gt;
&lt;/blockquote&gt;

Then, in things like the quickstart app, I just went into the library directory and did 

&lt;blockquote&gt;
  &lt;pre&gt;
ln -s /usr/local/ZendFramework/library/Zend
&lt;/pre&gt;
&lt;/blockquote&gt;

Finally, in the quickstart, I did the requisite 
&lt;blockquote&gt;
  &lt;pre&gt;
php scripts/load.sqlite.php --withdata
&lt;/pre&gt;
&lt;/blockquote&gt;

as dictated in the quickstart readme, and the db was created.

Still following the instructions in the quickstart readme, I created the virtual host. I put it into /etc/apache2/extra/httpd-vhosts.conf and uncommented the include in httpd.conf. I added the line in /etc/host but here's the thing: Add ::1 as well as 127.0.0.1 since, being a futurtistic Mac, it uses IPv6.

Apache had trouble with permissions when my docroot was in my home directory, so my virtual host's docroot ended up being /Library/WebServer/ZendFrameworkQuickstart-20090430

If you have permissions issues (you will), look in the apache log and chmod everything in sight.

Finally, the app worked!

Next, I tried making an app from scratch using the zh.sh script that comes with the framework. It's a bit like the RoR script(s) and is used to generate a new app, a new controller, a new view, etc. I made a do-nothing app and voila! it worked!

&lt;blockquote&gt;
  &lt;pre&gt;
zf.sh create controller auth 
zf.sh create action login auth
zf.sh create action logout auth --view-included=0
&lt;/pre&gt;
&lt;/blockquote&gt;

Still, the virtual host stuff has to be set up or nothing else will work. That's very troubling, as I can't imagine many ISPs being open to that level of messing with their Apache instance. More on that particular nightmare another time.
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-5543906304204223674?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/5543906304204223674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=5543906304204223674' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5543906304204223674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5543906304204223674'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/06/php-again.html' title='PHP Again'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-2227763955094085550</id><published>2009-06-13T21:47:00.001-07:00</published><updated>2009-06-13T21:47:45.826-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ldap'/><title type='text'>Notes on setting up an LDAP server</title><content type='html'>&lt;p&gt;Install OpenLDAP if you don't already have it.&lt;br /&gt;
Use WebMin to configure it. The defaults are pretty good.&lt;br /&gt;
Do this so you don't get complaints on startup:&lt;br /&gt;
cp /etc/openldap/DB_CONFIG.example /var/lib/ldap/DB_CONFIG&lt;br /&gt;
restart TWICE. The first time there will be another warning. After that, no more warnings.&lt;/p&gt;
&lt;p&gt;Install phpLDAPadmin. Copy the example config as described in the setup instructions.&lt;br /&gt;
To verify that it works, try this:&lt;br /&gt;
ldapsearch -x -b 'dc=montessorifamily,dc=com' '(objectclass=*)'&lt;/p&gt;
&lt;p&gt;To verify the auth, do this:&lt;br /&gt;
ldapsearch -x -b 'dc=montessorifamily,dc=com' '(objectclass=*)' -D 'cn=Manager,dc=montessorifamily,dc=com' -W&lt;/p&gt;
&lt;p&gt;The "-x" says "use simple auth instead of SASL"&lt;/p&gt;Create the basic structure by putting this into a file:
&lt;pre&gt;
&lt;code&gt;dn:     dc=montessorifamily, dc=com
objectClass:    top
objectClass:    dcObject
objectClass:    organization
dc:     montessorifamily
o:      Montessori Family School
dn:     ou=addressbook, dc=montessorifamily, dc=com
objectClass:    top
objectClass:    organizationalUnit
ou:     addressbook&lt;/code&gt;
&lt;/pre&gt;

Do not use a cleartext password in slapd.conf or WebMin won't know how to auth. Use WebMin to set the password and it'll use the '{crypt]' syntax and all will be well.

phpLDAPAdmin doesn't seem happy with simple auth. Change it, or change LDAP?

'person', 'inetOrgPerson', 'organizationalPerson' are part of core.schema And the plural of schema is schemata (or "schemas" in a pinch.)

See &lt;a href="http://www.onlamp.com/pub/a/onlamp/2003/03/27/ldap_ab.html?page=1"&gt;OnLamp article&lt;/a&gt;

This &lt;a href="http://www.linux-mag.com/id/948"&gt;Linux Magazine article&lt;/a&gt; requires one to register at their site. There is more about security, schemata, and replication, so I ignored it.
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-2227763955094085550?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/2227763955094085550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=2227763955094085550' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/2227763955094085550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/2227763955094085550'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/06/notes-on-setting-up-ldap-server.html' title='Notes on setting up an LDAP server'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-4950903159753348538</id><published>2009-06-13T21:46:00.001-07:00</published><updated>2009-06-14T19:16:48.919-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>TurboGears? Hmmm. Try Django.</title><content type='html'>&lt;p&gt;I'm going for 2.0.&lt;/p&gt;
&lt;p&gt;Following the instructions here:&lt;/p&gt;
&lt;p&gt;sudo easy_install -i http://www.turbogears.org/2.0/downloads/current/index tg.devtools&lt;/p&gt;
&lt;p&gt;Naturally, I got complaints, so I had to do this:&lt;br /&gt;
easy_install -U setuptools&lt;/p&gt;
&lt;p&gt;Nope. It seems that no force on earth can update the default MacOS install of setuptools, so I just deleted it. The newer one had been put into /usr/local/bin by previous attempts to update setuptools (which is what the error message told me to do.)&lt;/p&gt;
&lt;p&gt;We're still gonna need db drivers, so&lt;br /&gt;
sudo easy_install MySQL_python&lt;/p&gt;
&lt;p&gt;The driver for sqlite is allegedly already part of Python.&lt;/p&gt;
&lt;p&gt;So back to the install of TurboGears. The 2.0 docs are full of talk of "virtual environments" which makes me queasy. The reason I'm doing Python is simplicity, and that shit is not simple.&lt;/p&gt;
&lt;p&gt;Like RoR (and PHP's ZF as I discovered) there is a CLI tool that sets things up. It's called paster.&lt;/p&gt;
&lt;p&gt;So we follow the directions here: http://turbogears.org/2.0/docs/main/QuickStart.html — very well written, btw.&lt;/p&gt;
&lt;p&gt;paster quickstart&lt;br /&gt;
blah blah blah&lt;/p&gt;
&lt;p&gt;This is hell! It's worse than the PHP stuff! I wanted to go Python for simplicity, but this is a Heavy Weight Framework. Sheesh. Oh, it looks like a nice enough framework, but I am not looking for a PhD in frameworks. I just wanna get my app out the door! And, most important, I need something that is ISP-friendly. I simply cannot imagine doing all these arcane gymnastics in a user directory without root access.&lt;/p&gt;
&lt;p&gt;Along the way I did&lt;br /&gt;
sudo port install python_select&lt;/p&gt;
&lt;p&gt;and I love it!&lt;/p&gt;
&lt;p&gt;So a quick&lt;br /&gt;
sudo python_select python26&lt;br /&gt;
and off to install django:&lt;br /&gt;
sudo port install py26-django&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-4950903159753348538?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/4950903159753348538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=4950903159753348538' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/4950903159753348538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/4950903159753348538'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/06/turbogears-hmmm-try-django.html' title='TurboGears? Hmmm. Try Django.'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-7880407819645211066</id><published>2009-05-13T21:59:00.001-07:00</published><updated>2009-05-13T21:59:22.821-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='fedora'/><title type='text'>Bootstrapping Java on Fedora</title><content type='html'>&lt;p&gt;Every time I have to bootstrap a new box with Java, it's a learning experience. I sure wish it was easy. The hardest part this time 'round was finding Java. Sun sure goes to a lot of trouble to hide it.&lt;br /&gt;
Found this:&lt;br /&gt;&lt;/p&gt;
&lt;blockquote cite="http://blog.taragana.com/index.php/archive/how-to-install-jdk-6-java-se-6-tomcat-in-fedora-core-6-fedora-7-in-5-minutes/"&gt;
  &lt;br /&gt;
  [&lt;a href="http://blog.taragana.com/index.php/archive/how-to-install-jdk-6-java-se-6-tomcat-in-fedora-core-6-fedora-7-in-5-minutes/"&gt;&lt;cite&gt;How To Install JDK 6 / Java SE 6 (+ Tomcat) in Fedora Core 6 / Fedora 7 in 5 Minutes&lt;/cite&gt;&lt;/a&gt;]&lt;br /&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is a &lt;a href="http://download.java.net/jdk6/binaries/"&gt;secret directory&lt;/a&gt; where you can download JDKs and just install. The end.&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-7880407819645211066?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/7880407819645211066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=7880407819645211066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/7880407819645211066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/7880407819645211066'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/05/bootstrapping-java-on-fedora.html' title='Bootstrapping Java on Fedora'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-5545606942359107981</id><published>2009-05-03T22:11:00.001-07:00</published><updated>2009-05-03T22:11:19.401-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='wicket'/><title type='text'>Wicket</title><content type='html'>&lt;p&gt;So I started by using the &lt;a href="http://wicket.apache.org/quickstart.html"&gt;QuickStart&lt;/a&gt; tool to generate the correct Maven incantation. (I'm already hating Maven) and following the instructions there in my Eclipse workspace. This generated a whole tree of stuff: my new project. The artifactId I specified ended up naming the root of the tree.&lt;/p&gt;
&lt;p&gt;Next – still following the instructions – I went into the project and did this: &lt;code&gt;mvn eclipse:eclipse -DdownloadSources=true&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;After that, into Eclipse and tell it to create a new Java project. I gave it the name I'd already chosen (the ArtifactId) and Eclipse noticed that there was a project there to import. Cool.&lt;/p&gt;
&lt;p&gt;Unfortunately, it uses an eclipse "variable" called M2_REPO in the classpath, so this need to be resolved. I opened my Eclipse preferences and navigated to Java &amp;gt; Build Path &amp;gt; Classpath variables and set M2_REPO to point to $HOME/.m2/repository&lt;/p&gt;
&lt;p&gt;But Eclipse still wasn't aware that it needs to copy the .html files to the output ("target") directory. That's because the generated .project explicitly includes only .java files in the source path. To remedy, open the project properties and go to the Source tab in Java Build Path. Add an inclusion pattern for "**/*.html" to the one already there for the .java files.&lt;/p&gt;
&lt;p&gt;Great! A working wiket app. That wasn't too bad.&lt;/p&gt;
&lt;p&gt;So what about Wicket Bench, the Eclipse plugin? Out of date. It points to its own internal Wicket distro, which is old. Nice idea otherwise, and TDD-friendly.&lt;/p&gt;
&lt;p&gt;Next, I tried one of the apps included in the Wicket download. There's a pom.xml there, so maybe I can get to run as a standalone app? Too many missing pieces.&lt;/p&gt;
&lt;p&gt;At this point I am miffed. What a mess! Every other thing I touch is out of date, but as a n00b, I have no way of knowing which is the new and which is the old.&lt;/p&gt;
&lt;p&gt;So, my latest strategy is this: Use the archetype stuff from the QuickStart tool, and then &lt;em&gt;copy&lt;/em&gt; needed pieces in from other parts of the distro – in my case, the auth &amp;amp; auth sample code. We'll see how that goes.&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-5545606942359107981?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/5545606942359107981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=5545606942359107981' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5545606942359107981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5545606942359107981'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/05/wicket.html' title='Wicket'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-31845738983800350</id><published>2009-05-02T19:15:00.001-07:00</published><updated>2009-05-02T19:15:08.902-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Perl for no good reason</title><content type='html'>I wanted to install webmin on a whim. It's all perl, so I thought I'd fire up cpan and update my perl. That was a massive undertaking, as most of my perl install was what came with the OS. Naturally, there were numerous problems. Most of them were traced to a myserious "only available with the XS version" error message, for which &lt;a href="http://blog.zacharyarmstrong.com/2008/05/24/fixing-the-perl-module-only-available-with-the-xs-version-error/"&gt;this post&lt;/a&gt; was the cure.

It too several tries to get CPAN itself updated along with a gazilion modules, but it's all good.
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-31845738983800350?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/31845738983800350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=31845738983800350' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/31845738983800350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/31845738983800350'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/05/perl-for-no-good-reason.html' title='Perl for no good reason'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-5295043167478032780</id><published>2009-04-09T08:09:00.000-07:00</published><updated>2009-04-09T08:49:06.739-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogger'/><title type='text'>Blogger.com is always painful</title><content type='html'>&lt;p&gt;Blogger.com managed to get itself blocked by my ISP — again. The problem is that even though the authorization credentials are wrong, blogger.com keeps trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and trying and eventually gets itself blocked.&lt;/p&gt;
&lt;p&gt;That's a pain. I have to open a ticket and, with cap in hand, ask my ISP to please unblock the marauding googler.&lt;/p&gt;
&lt;p&gt;My blog is back up, and I have successfully (?) moved my web service to a new server. Mail is being done incrementally, but we expect no interruption in service. (Hear that Mr. Murphy?)&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-5295043167478032780?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/5295043167478032780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=5295043167478032780' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5295043167478032780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5295043167478032780'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/04/test.html' title='Blogger.com is always painful'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-885591243491630156</id><published>2009-04-09T01:42:00.001-07:00</published><updated>2009-04-09T01:56:44.297-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>"gem update" and native gibblies</title><content type='html'>&lt;p&gt;I tried running &lt;code&gt;gem update&lt;/code&gt; on my new Joyent "shared accelerator" (translation: &lt;em&gt;hosting service&lt;/em&gt;)&lt;/p&gt;This is what happened:
&lt;pre&gt;
&lt;code&gt;[marin:~] jdtangney$ gem update
Updating installed gems
Updating eventmachine
WARNING:  Installing to ~/.gem since /usr/local/lib/ruby/gems/1.8 and
/usr/local/bin aren't both writable.
Building native extensions.  This could take a while...
ERROR:  While executing gem ... (Gem::Installer::ExtensionBuildError)
ERROR: Failed to build gem native extension.
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;The &lt;em&gt;nice&lt;/em&gt; part is that it automatically noticed that it needed to do a local install. But that cryptic error message — wtf?&lt;/p&gt;Looking down a little further in the spew, I saw
&lt;pre style="overflow-x: scroll; width: 600px"&gt;
&lt;code&gt;shared -o rubyeventmachine.so epoll.o emwin.o ssl.o ed.o sigs.o cplusplus.o em.o pipe.o rubymain.o files.o binder.o kb.o cmain.o page.o -L. -L/usr/local/lib -Wl,-R/usr/local/lib -L. -L/usr/lib -Wl,-R/usr/lib -L/usr/local/lib -Wl,-R/usr/local/lib -Wl,-R/usr/local/lib -L/usr/local/lib  -Wl,-R -Wl,/usr/local/lib -L/usr/local/lib -lruby18 -lsocket -lnsl  -lssl -lcrypto -lsocket -lnsl -ldl   -lpthread -ldl -lcrypt -lm -lm -lpthread -lrt -ldb4  -lc
sh: shared: not found&lt;/code&gt;
&lt;/pre&gt;So some googling later... I just executed this before running &lt;code&gt;gem update&lt;/code&gt;:
&lt;pre&gt;
&lt;code&gt;export CXX=g++&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;It now gets a lot further... Next run ran out of memory?! The one after that segfaulted! (No, really!) The third run ran to a successful completion. Sheesh.&lt;/p&gt;
&lt;p&gt;RubyGems seems to be in the same state of fragility that fink was in several years ago. There are just too many exceptions and funky, weird configurations one has to do to get it to work.&lt;/p&gt;
&lt;p&gt;I had hoped that by being a late adopter, I would miss out on all this chaos. I guess not.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-885591243491630156?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/885591243491630156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=885591243491630156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/885591243491630156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/885591243491630156'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/04/update-and-native-gibblies.html' title='&amp;quot;gem update&amp;quot; and native gibblies'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-931414434304372006</id><published>2009-04-05T14:03:00.001-07:00</published><updated>2009-04-05T14:03:04.774-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='macos'/><title type='text'>Installing MySQL gem on Leopard</title><content type='html'>&lt;p&gt;Ordinarily, installing a gem on Mac OS X is as simple as&lt;/p&gt;
&lt;pre&gt;
&lt;code&gt;sudo gem install foo&lt;/code&gt;.
&lt;/pre&gt;
&lt;p&gt;However, a little extra magic is required to install the mysql gem:&lt;/p&gt;
&lt;pre&gt;
&lt;code&gt;sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;I found &lt;a href="http://www.macruby.org/trac/wiki/Troubleshooting"&gt;this reference&lt;/a&gt; to back me up.&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-931414434304372006?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/931414434304372006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=931414434304372006' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/931414434304372006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/931414434304372006'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/04/installing-mysql-gem-on-leopard.html' title='Installing MySQL gem on Leopard'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-8547468126441599487</id><published>2009-04-01T21:01:00.001-07:00</published><updated>2009-04-09T02:01:27.985-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='filemaker'/><title type='text'>Front end to FMP</title><content type='html'>&lt;p&gt;I need to build a Q&amp;amp;D front end for a FileMaker database. While the Server version of FileMaker ships with some PHP glue, I decided to go with a more familiar environment. Python! It's a nice language. I have some familiarity with it, and (most important of all) it works on the ISP's server.&lt;/p&gt;
&lt;p&gt;I did a quick survey of some lightweight Python frameworks, and settled on &lt;a href="http://turbogears.org/"&gt;TurboGears&lt;/a&gt; (with &lt;a href="http://www.cherrypy.org/"&gt;CherryPy&lt;/a&gt;) for the app itself. For the interface to FileMaker, I found &lt;a href="http://code.google.com/p/pyfilemaker/"&gt;PyFileMaker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ready to go! So, to begin with, I did a little spiking to kick the tires of PyFileMaker. Right out the gate, the results were disappointing. The code choked on my password! (Some regex seemed to believe that my password shouldn't contain special characters.) Not a problem: I created a special account for PyFileMaker (not a bad idea anyway for production) and got one teensy step further. I hit our FMP Server and asked for a list of databases. Kapow! Now PyFileMaker complained that one of the db names "contain unsupported characters." Pity it doesn't deign to tell me which one...&lt;/p&gt;
&lt;p&gt;Well!&lt;/p&gt;
&lt;p&gt;Foreseeing a life of misery and pain, I looked for a Ruby solution. A quick trip to the ISP... Whew! Ruby works there too. Anyway, it's high time I learned Ruby, so next stop, &lt;a href="http://sixfriedrice.com/wp/products/rfm/"&gt;Rfm&lt;/a&gt; The visit to the six.fried.rice site was a breath of fresh air. I know from previous googling journeys that they seem to know what they're talking about. Best of all, they have a RoR sample app that talks to a FMP db, so I can start with that.&lt;/p&gt;
&lt;p&gt;Into the world of Ruby!&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-8547468126441599487?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/8547468126441599487/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=8547468126441599487' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/8547468126441599487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/8547468126441599487'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/04/front-end-to-fmp.html' title='Front end to FMP'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-3481818485229901839</id><published>2009-03-29T13:43:00.001-07:00</published><updated>2009-03-29T13:43:15.753-07:00</updated><title type='text'>Test post</title><content type='html'>&lt;div&gt;I am doing &lt;a href="http://www.43things.com"&gt;43 things&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-3481818485229901839?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/3481818485229901839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=3481818485229901839' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/3481818485229901839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/3481818485229901839'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/03/test-post.html' title='Test post'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-6956223122553959630</id><published>2009-03-24T00:49:00.001-07:00</published><updated>2009-03-24T00:49:37.648-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogger'/><title type='text'>Publishing your blog is taking longer than expected.</title><content type='html'>&lt;p&gt;Blogger.com goes spastic now and again. For the last few days, I have been unable to (re-)publish this blog, due to a mysterious "Publishing your blog is taking longer than expected." After that, I get a twitchy "Your blog published with errors." page without mention of what the particular errors are.&lt;/p&gt;
&lt;p&gt;Needless to say, this has all been working for years without change.&lt;/p&gt;
&lt;p&gt;I fixed the ftp path – somewhere was a mention that it must not be absolute. It had to be changed in several places for the blog pages, the atom and rss files and the blog archives. I had to keep clicking that "To continue waiting for it to finish, click here" link, but it still didn't work.&lt;/p&gt;
&lt;p&gt;Some sort of error message sure would be helpful.&lt;/p&gt;
&lt;p&gt;Meanwhile, I am about to give up on this ftp stuff and have blogger host the blog itself. I'll have to do a little magic to make it integrate nicely with the site, but how hard could it be?&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-6956223122553959630?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/6956223122553959630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=6956223122553959630' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/6956223122553959630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/6956223122553959630'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2009/03/publishing-your-blog-is-taking-longer.html' title='Publishing your blog is taking longer than expected.'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-7431696757460194707</id><published>2008-12-09T23:04:00.001-08:00</published><updated>2008-12-09T23:04:55.341-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><title type='text'>NIH</title><content type='html'>&lt;p&gt;Before I knew what National Institutes of Health was, before I moved to the US, NIH stood for "&lt;a href="http://en.wikipedia.org/wiki/Not_Invented_Here"&gt;Not Invented Here.&lt;/a&gt;"&lt;/p&gt;
&lt;p&gt;The reappearance of this phenomenon on my radar is coincident with my deepening involvement in the Agile/XP world. Coincidence? I sure hope so. So step forward all you XPers and agilistas and tell me that you are at least as allergic to NIH as I am.&lt;/p&gt;
&lt;p&gt;In the last month I have spent hours (with a pair) figuring out why http session management is broken. I have spent &lt;em&gt;days&lt;/em&gt; (with various pairs) trying to outwit a half-baked Hibernate session management infrastructure. Today I spent several hours (with a pair) getting some file manipulation utilities to work.&lt;/p&gt;
&lt;p&gt;Even back in the days of Struts 0.5, session management was pretty damned solid. And the Spring-like management of Hibernate sessions by tying them to a request/response cycle (in the simplest case) was hashed out years ago. And the &lt;a href="http://commons.apache.org/io/" style="background-color: rgba(0, 0, 0, 0); color: #DAA520; font-family: verdana; font-size: 11px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: underline; text-indent: 0px; clip-rule: nonzero; flood-color: #000000; flood-opacity: 1; lighting-color: #FFFFFF; stop-color: #000000; stop-opacity: 1; pointer-events: visiblepainted; color-interpolation: srgb; color-interpolation-filters: linearrgb; color-rendering: auto; fill: #000000; fill-opacity: 1; fill-rule: nonzero; image-rendering: auto; shape-rendering: auto; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; text-rendering: auto; alignment-baseline: auto; baseline-shift: baseline; dominant-baseline: auto; text-anchor: start; writing-mode: lr-tb; glyph-orientation-horizontal: 0deg; glyph-orientation-vertical: auto;"&gt;Apache commons I/O&lt;/a&gt; library is pretty mature at this point. Hell, it's already on our classpath!&lt;/p&gt;
&lt;p&gt;So how did this mess come to be? The answers I got in the past were vague hand-waves along the lines of "well we needed something simple and lightweight so we built our own."&lt;/p&gt;
&lt;p&gt;Yeah, yeah, "the simplest thing that could possibly work." But surely the definition of "work" also includes "does not require constant repair and debugging"?&lt;/p&gt;
&lt;p&gt;Maybe it's just innocence. Maybe those people really believe that an app framework is "too big" and so building out a Struts-lookalike from scratch is excusable. Maybe they really believe that they just know they will never need to manage Hibernate sessions with a broader scope than a single call. Maybe they really believe the file manipulation is just a quickie, undeserving of a library.&lt;/p&gt;
&lt;p&gt;To me the &lt;em&gt;simplest&lt;/em&gt; thing that could possibly &lt;em&gt;work&lt;/em&gt; is to use code that someone else has spent years refining and is known to work.&lt;/p&gt;
&lt;p&gt;Please tell me all this NIH is not hubris.&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-7431696757460194707?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/7431696757460194707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=7431696757460194707' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/7431696757460194707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/7431696757460194707'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2008/12/nih.html' title='NIH'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-6458766152742078815</id><published>2008-11-28T22:05:00.001-08:00</published><updated>2008-11-28T22:05:09.844-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><category scheme='http://www.blogger.com/atom/ns#' term='filemaker'/><title type='text'>Migrating from FileMaker to MySQL</title><content type='html'>&lt;p&gt;FileMaker Pro (FMP) has the ability to access a real RDBMS via ODBC dynamically. An "external" table can be accessed in the same way as a native FMP table. FMP calculations, normally associated with a native FMP table, can be added to an external table as "supplementary fields".&lt;/p&gt;
&lt;p&gt;So all this sounds terribly glorious. Surely one can migrate one's FMP db to MySQL (or other) so that the data is stored in an industrial-strength RDBMS. That, naturally, allows all kinds of other enterprise apps to hit the same data as the FMP. In fact, one can think of the FMP db as a front end to the enterprise db.&lt;/p&gt;
&lt;p&gt;I know folks who have made this work. But &lt;em&gt;migrating&lt;/em&gt; is another story. There is no programatic interface to the FMP schema - the definitions of the tables and "table occurrences" (really aliases that allow for the definition of associations that become joins at run time). And FMP's use internally of ids rather than names for fields, scripts, tables, etc – one of its key benefits that allows transparent renaming of objects – means that once a relationship is defined using one table, the only way to switch to another (external) table is to delete and recreate it.&lt;/p&gt;
&lt;p&gt;That spells a ton of manual labor. I'll outsource it if I can find someone.&lt;/p&gt;
&lt;p&gt;We'll still be left with all the presentation intelligence (FMP layouts) as well as the business logic (scripts, calculated fields, portals) firmly in the FMP world. As we build a parallel implementation that does not rely on FMP, we'll be rebuilding all that stuff. Only this time we'll do it in a transparent, modifiable, refactorable way, using code that can be edited using industry-standard tools like (ooh, gasp) a text editor.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;So if you're thinking of building a real enterprise app in FMP, don't. It &lt;em&gt;will&lt;/em&gt; bite you.&lt;/p&gt;
&lt;p&gt;And to answer my own questions from a few months ago regarding FMP in an XP world: The more I bang my head against the closed, constrained FMP model, the more I realize that its only use is as a spiking tool.&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-6458766152742078815?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/6458766152742078815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=6458766152742078815' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/6458766152742078815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/6458766152742078815'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2008/11/migrating-from-filemaker-to-mysql.html' title='Migrating from FileMaker to MySQL'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-7814926629462513862</id><published>2008-11-27T14:24:00.001-08:00</published><updated>2008-11-28T23:37:39.465-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='macos'/><title type='text'>Ecto</title><content type='html'>&lt;p&gt;So it's a holiday, and what better way to spend it than fiddling with an app on a Mac?&lt;/p&gt;
&lt;p&gt;I looked around – once again – for a better blog posting client than &lt;a href="http://illuminex.com/ecto/"&gt;ecto&lt;/a&gt;. The only contender is &lt;a href="http://www.drinkbrainjuice.com/blogo"&gt;blogo&lt;/a&gt;. It's very nice, but it lacks some of the power features of ecto like a twitter plugin (I still don't have that working..), the ability to ping a bunch of servers, and, most important, custom HTML tags for doing stuff like posting code. Sure, you can hand-edit the HTML, but that gets very old very quickly.&lt;/p&gt;
&lt;p&gt;So back to ecto. Time to pimp it up and get all the gibblies to work together. The UI has always frustrated me. Nothing is where I expect it to be. But at least this version (3.0b55) is reasonably stable.&lt;/p&gt;
&lt;p&gt;Now, having got it the way I want it, I need to set it up again on my desktop machine. What a pain! I copied the .plist file from &lt;code&gt;~/Library/Preferences&lt;/code&gt; to the other Mac, but some things are still not there, like the list of servers to ping. With a little digging and some help from &lt;code&gt;sudo fs_usage -filesys |fgrep -i ecto&lt;/code&gt; I see that all that stuff lives in &lt;code&gt;~Library/Application Support/ecto3/accounts.plist&lt;/code&gt; Bingo!&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-7814926629462513862?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/7814926629462513862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=7814926629462513862' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/7814926629462513862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/7814926629462513862'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2008/11/ecto.html' title='Ecto'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-4737231760030451179</id><published>2008-10-11T14:19:00.000-07:00</published><updated>2009-05-18T21:19:00.769-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='macos'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='filemaker'/><title type='text'>PHP and FMP</title><content type='html'>&lt;p&gt;Get &lt;code&gt;FM_API_for_PHP_Standalone&lt;/code&gt; from within the FM server download. Use the trial if necessary.&lt;/p&gt;
&lt;p&gt;Expand it and copy it into &lt;code&gt;/usr/local/php/fmp&lt;/code&gt;. Make the parent directories as needed&lt;/p&gt;
&lt;p&gt;Copy &lt;code&gt;/etc/php.ini.default&lt;/code&gt; to&lt;span style="font-family: -webkit-monospace;"&gt;/etc/php.ini&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Edit php.ini. Uncomment and modify &lt;span style="font-family: -webkit-monospace;"&gt;include_path = ".:/usr/local/php/includes"&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I set up eclipse by copying the features and plugins after downloading from &lt;a href="http://www.eclipse.org/pdt/downloads/"&gt;http://www.eclipse.org/pdt/downloads/&lt;/a&gt; I couldn't get the update site to work (mysterious errors.) Finally, after messing with it for ages, I concluded that Eclipse PDT doesn't work with Ganymede. I now use &lt;a href="http://phpeclipse.net/"&gt;PHPEclipse&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For debugging, we need xdebug. Oopsie. Must install pear to get pecl to get xdebug.&lt;/p&gt;
&lt;p&gt;So,&lt;/p&gt;
&lt;blockquote&gt;
  &lt;pre&gt;
curl http://pear.php.net/go-pear &amp;gt; go-pear.php
sudo php -q go-pear.php
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let the script update php.ini. And don't forget to update PATH like the script told you to.&lt;/p&gt;
&lt;p&gt;Then it's&lt;/p&gt;
&lt;blockquote&gt;
  &lt;pre&gt;
sudo pecl install xdebug
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;And do NOT do what it says (&lt;span style="font-family: -webkit-monospace;"&gt;You should add "extension=xdebug.so" to php.ini")&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Instead, add this:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;pre&gt;
[xdebug]
zend_extension=/usr/lib/php/extensions/no-debug-non-zts-20060613/xdebug.so
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then confirm that it's working by doing php -mxdebug will show up both under [PHP Modules] and [Zend Modules]&lt;/p&gt;
&lt;p&gt;Get phpUnit installed. See Sebastian Bergmann's site: &lt;a href="http://www.phpunit.de/manual/3.4/en/installation.html"&gt;http://www.phpunit.de/manual/3.4/en/installation.html&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;pre&gt;
sudo pear channel-discover pear.phpunit.de
sudo pear install phpunit/PHPUnit
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-4737231760030451179?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/4737231760030451179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=4737231760030451179' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/4737231760030451179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/4737231760030451179'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2008/10/php-and-fmp.html' title='PHP and FMP'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-3662872130648519889</id><published>2008-08-07T22:12:00.000-07:00</published><updated>2008-08-08T06:56:24.894-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><title type='text'>Wired</title><content type='html'>&lt;p&gt;All of my on-stage experience to date has been unplugged. That is, I have never dealt with amplification of any sort. I have sung the lead in operettas and musicals of all sorts as well as numerous musical roles, of course. All of it unamplified. But I have never – until tonight – had to sing onstage with a full band, had to deal with mic technique, had to try to follow exactly where the hell we are in the song with a monitor blaring the bass line alone...&lt;/p&gt;
&lt;p&gt;The "Music Masti" at Agile2008 was my wired debut. Damn, it's hard to figure out where you are, to keep track, to be able to hear un-monitored instruments when you are singing in a band.&lt;/p&gt;
&lt;p&gt;Now I have designed sound for stage productions, even mic'ing actors where needed. But now I know what it's like to be on the performing end. Who'd a' thunk it was so hard? This is what happens when you let popular culture pass you by.&lt;/p&gt;
&lt;p&gt;Sigh. There's a lesson in this. There is no substitute for doing, even when it seems that "it" is a natural extension of what one already knows. Maybe it's the geek mystique: "How hard could it be?" But when you pick up that mic and you realize that it's actually &lt;em&gt;not&lt;/em&gt; that self-evident,.. it's no longer an extrapolation from the known the assumed, but genuinely into the unknown, it's a bit of shock.&lt;/p&gt;
&lt;p&gt;Regardless, it was unbelievable fun.&lt;/p&gt;
&lt;p&gt;Rock on!&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-3662872130648519889?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/3662872130648519889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=3662872130648519889' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/3662872130648519889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/3662872130648519889'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2008/08/wired.html' title='Wired'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-4035514348146020582</id><published>2008-08-07T22:10:00.000-07:00</published><updated>2008-08-08T06:56:30.542-07:00</updated><title type='text'>tSQLt</title><content type='html'>&lt;p&gt;I attended a demo today in which tSQLT was put through its paces. It's a microtesting framework for databases. So what makes this one different? For one, the two dudes who presented totally &lt;em&gt;get&lt;/em&gt; TDD. The framework eats its own dogfood (it was TDD'ed with itself.)&lt;/p&gt;
&lt;p&gt;Downside? So far, it appears to be MS SQL Server-only. It's "pre-alpha" in the words of the authors, so it may not be as mature as one might like.&lt;/p&gt;
&lt;p&gt;Still, the promise of real, grown-up TDD in a database is mighty appealing.&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-4035514348146020582?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/4035514348146020582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=4035514348146020582' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/4035514348146020582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/4035514348146020582'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2008/08/tsqlt.html' title='tSQLt'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-6733835716289823768</id><published>2008-07-30T11:12:00.000-07:00</published><updated>2008-07-30T11:53:01.436-07:00</updated><title type='text'>FileMaker – the war continues</title><content type='html'>&lt;p&gt;Now that I am starting to add some web-visible components to the SIS I am building with FMP, I finally have the opportunity to test-drive what I'm doing. What a pleasure it is to make a Selenium script that logs in, clicks around, types a bit and validates the contents of the web pages!

&lt;p&gt;Of course, the best part of test-driving (albeit in this rather coarse, macro way sans microtests) is that it is so much faster! I spent a few minutes putting the script together. I didn't even bother using Selenium-RC but instead just run the thing straight from the IDE. Then, logging in with the right credentials and doing all the preliminary navigation is done precisely &lt;span class="Apple-style-span" style="font-style: italic;"&gt;once&lt;/span&gt; in my script. I don't have to do that mind-numbing, repetitive work that machines enjoy but I don't.

&lt;p&gt;The test, simple as it is, is a one-click, red/green litmus test. If it's red, I hack around in the gibblies of my app, and click again. Rinse and repeat. When it's green, I refactor a little then check in.

&lt;p&gt;Of course, checking in a giant FileMaker file as an opaque, binary monolith really only has value as a backup. There ain't no way anyone's ever going to do a diff on those puppies. Maybe I should take the extra 5 minutes to generate a new DDR in XML and check &lt;span class="Apple-style-span" style="font-style: italic;"&gt;that&lt;/span&gt; in.

&lt;p&gt;And since you brought it up, refactoring's a larf in FMP. Maybe I'll write a book called "Refactoring to FMP Patterns." In reality, all I actually do is to get rid of any debug fields or relationships I created. 

&lt;p&gt;While the scripts seem like an obvious target, the real, hard-core refactoring of scripts is something I have skirted. As I mentioned in a previous post, the overhead of passing parameters into a "sub-script" feels like it outweighs the putative benefits. Maybe there are some tricks that I can come up with... I'll have to think about this more seriously. 

&lt;p&gt;Meanwhile, even if we can't do much beyond the basics regarding the size of scripts, we can start with intention-revealing names for scripts and variables. Deep nesting of if's might be reduced by using guard clauses.

&lt;p&gt;Other refactorings might come from the database world. At least that's well-understood! Most of the time it's not much of an issue for the schema itself; it's a question of factoring correctly in the first place, thereby obviating the necessity to &lt;span class="Apple-style-span" style="font-style: italic;"&gt;re&lt;/span&gt;-factor. It's not rocket surgery: normalize the schema. Don't duplicate. Consider whether a 1-1 relationship is worth the overhead of maintaining it. The usual bitrot kinds of things like lousy names of fields and tables are quite trivial to deal with in the FMP world – references are transparently updated.

&lt;p&gt;Layouts, being primarily collections of visual elements, yield to modest refactoring goals like maintainability through revelation of intention. Reduction of duplication by parameterizing the layout is not something I have pursued very rigorously. There is probably room for exploration there. One concern is that supporting such techniques might require introducing temporary tables. I suppose I shouldn't be afraid of that, but the though of copying data back and forth just seems like a lot of heavy lifting, again outweighing the minor inconvenience of duplication. Sigh. Another area I guess I need to delve into a bit more deeply.

&lt;p&gt;Although FMP retains references to internal objects by some means other than their names (so you can, e.g. rename a table and all references to it show the new name), it's possible to delete some objects and leave unused objects in the file. This is where an analysis tool is yer only man. It often takes several passes to get a file "clean", but it's worth it as a regular part of pre-checkin refactoring hygiene.

&lt;p&gt;While writing this, I have noticed areas that might be fertile ground for further XP-oriented study. You'll be the first to know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-6733835716289823768?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/6733835716289823768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=6733835716289823768' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/6733835716289823768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/6733835716289823768'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2008/07/filemaker-war-continues.html' title='FileMaker – the war continues'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-5723483550272491675</id><published>2008-07-27T20:20:00.001-07:00</published><updated>2008-07-27T20:20:56.061-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='user interface'/><title type='text'>Readings on User Interface for Children's Interactive Media</title><content type='html'>&lt;p&gt;There is a quiet, but knowledgeable community on the ACM's CHI-Kids mailing list. A reader had requested references to "user interface standards and guidelines for children ages 3 to 6 years old. " Another reader collected them, and they are now posted &lt;a href="http://dustormagic.wikispaces.com/Readings"&gt;on this wiki.&lt;/a&gt;&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-5723483550272491675?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/5723483550272491675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=5723483550272491675' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5723483550272491675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/5723483550272491675'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2008/07/readings-on-user-interface-for-children.html' title='Readings on User Interface for Children&amp;#39;s Interactive Media'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5369352.post-2792540801134347287</id><published>2008-07-25T16:51:00.000-07:00</published><updated>2008-08-08T06:56:19.504-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><title type='text'>Disgruntled employees</title><content type='html'>&lt;p&gt;I caught a bit of this morning's Forum on KQED (&lt;a href="http://www.kqed.org/.stream/anon/radio/forum/2008/07/2008-07-25a-forum.mp3"&gt;Download (MP3)&lt;/a&gt;) which was mostly about some civil servant in SF who sabotaged the City's computer systems, and what that means for employers and "health and security of the workplace."&lt;/p&gt;
&lt;p&gt;The interesting bit for me was a Towers Perrin survey of 90,000 employees across 18 countries indicating "widespread disengagement".&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;21% "engaged with their work"&lt;/li&gt;

  &lt;li&gt;38% "partly or fully disengaged"&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also cited was a Gallup survey saying that&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;19% of employees are "actively disengaged" i.e. trying to sabotage the workforce&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I bring this up because as XP evangelists we run into people who &lt;i&gt;we want&lt;/i&gt; to see succeed and excel, but who might be dealing with the own demons. And a much-cited antidote mentioned on the show was "job rotation" and "employees training each other". So pair programming is not just good for the code, good for the dev, good for the team, good for the enterprise, &lt;strong&gt;but&lt;/strong&gt; it might just stop you from going postal. ;-)&lt;/p&gt;
&lt;p&gt;Those numbers also tell us that there is a vast amount of waste. Large numbers of people punch clocks and little else. Again, as XPers, we talk about productivity, but what does that really mean for someone who is &lt;a href="http://en.wikipedia.org/wiki/Comfortably_Numb"&gt;comfortably numb&lt;/a&gt;?&lt;/p&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5369352-2792540801134347287?l=jdtangney.com%2Fblog'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/2792540801134347287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5369352&amp;postID=2792540801134347287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/2792540801134347287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5369352/posts/default/2792540801134347287'/><link rel='alternate' type='text/html' href='http://jdtangney.com/blog/2008/07/disgruntled-employees.html' title='Disgruntled employees'/><author><name>jdtangney</name><uri>http://www.blogger.com/profile/00888797728494413579</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15277872557741014052'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>