<?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' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-31053906</id><updated>2011-09-16T01:31:34.041-07:00</updated><category term='jboss'/><category term='64bit'/><category term='eclipse'/><category term='jruby'/><category term='java'/><category term='osx'/><category term='leopard'/><category term='intel'/><category term='rails'/><title type='text'>every phone ... ringing in unison</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-31053906.post-1469486326580291854</id><published>2009-06-01T21:32:00.001-07:00</published><updated>2009-06-01T21:33:00.563-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='jboss'/><title type='text'>Packaging a Rails 1.1 app for JRuby</title><content type='html'>I've recently needed to "convert" a Rails 1.1 app to run under JBoss using JRuby to improve the deployment story and long-term maintenance for a new virtual server. The configuration/conversion wasn't without significant hiccups. I'll try to cover in some detail here what I did to get things working.&lt;br /&gt;&lt;br /&gt;First, I tried upgrading to Rails 2.x. Don't try this. If you're not a professional Rails developer, you'll likely tear your hair out and ask yourself why you ever decided to use Rails in the first place. In my case, upgrading would have required a near total re-write of the (very simple) app.&lt;br /&gt;&lt;br /&gt;For the impatient, here's the basic gist of what I did.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;update config/boot.rb, require_gem -&gt; gem&lt;/li&gt;&lt;br /&gt;&lt;li&gt;freeze to edge, RELEASE=1.1.4&lt;/li&gt;&lt;br /&gt;&lt;li&gt;reset config/boot.rb(?) -&gt; rake rails:update&lt;/li&gt;&lt;br /&gt;&lt;li&gt;pluginize warbler&lt;/li&gt;&lt;br /&gt;&lt;li&gt;update environment.rb&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;create jboss-web.xml&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;create -ds.xml file&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;create warble.rb&lt;/li&gt;&lt;br /&gt;&lt;li&gt;update warble.rb&lt;/li&gt;&lt;br /&gt;&lt;li&gt;update database.yml -- copy production: block&lt;/li&gt;&lt;br /&gt;&lt;li&gt;update new/thankyou.rhtml (change absolute links)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;add close_connections.rb&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;edit new_rails_defaults.rb&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;I used JRuby 1.2.0 on a Rails 1.1.4 app, deploying to a JBoss 4.2.0.GA application server against a MySQL 4.1 database.&lt;br /&gt;&lt;br /&gt;This isn't meant to be a list you can work off, merely a list showing what's involved, so if you count yourself amongst the faint of heart, stop here :).&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;update config/boot.rb, require_gem -&gt; gem&lt;/h4&gt;&lt;br /&gt;If you don't actually have the original RubyGems that you had when you started your Rails 1.x project, some things have changed. Most particularly, &lt;strong&gt;require_gem&lt;/strong&gt; is no longer deprecated, its GONE! So, edit &lt;pre&gt;config/boot.rb&lt;/pre&gt; by changing the two instances of &lt;strong&gt;require_gem&lt;/strong&gt; to simply &lt;strong&gt;gem&lt;/strong&gt;. That wasn't too hard :)&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; freeze to edge, RELEASE=1.1.4&lt;/h4&gt;&lt;br /&gt;Now you're ready to freeze. You really want to freeze because it will simplify things down the road for your warbler tasks and runtime within JRuby. Until I froze, I kept having oodles of issues that basically track down to various commands trying to do things in my Rails project whilst executing code from the latest Rails on my system (2.3.2, I think). You should be able to freeze to just about any RELEASE or TAG you want. Either of the following should work:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ rake rails:freeze:edge TAG=rel_1-1-4&lt;br /&gt;$ rake rails:freeze:edge RELEASE=1.1.4&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; reset config/boot.rb(?) -&gt; rake rails:update&lt;/h4&gt;&lt;br /&gt;Guess what? Now we need to undo step #2. But, this is pretty easy. You can either manually revert the changes you made to &lt;em&gt;boot.rb&lt;/em&gt;, or just run:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ rake rails:update&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Which, contrary to its name, shouldn't do anything terribly crazy other than reset your boot.rb back to what it was previously (and it does this now based on your *frozen* Rails, not whatever the latest is in your system).&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; pluginize warbler&lt;/h4&gt;&lt;br /&gt;Assuming you've installed &lt;a href="http://caldersphere.rubyforge.org/warbler/"&gt;Warbler&lt;/a&gt; (if you haven't, &lt;em&gt;gem install warbler&lt;/em&gt;) - let's take the road less travelled and pluginize. This keeps everything in a nice &lt;em&gt;local&lt;/em&gt; package. It also means you can use the normal &lt;strong&gt;rake&lt;/strong&gt; commands instead of &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;jruby -S warble &amp;lt;cmd&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Alright, to pluginize, straight from warbler's docs:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ jruby -S warble pluginize&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; update environment.rb&lt;/h4&gt;&lt;br /&gt;Not sure where I found this, but it appears to be essential. Running in the JRuby environment appears to take a a few gems that aren't included elsewhere, so update your &lt;pre&gt;config/environment.rb&lt;/pre&gt; to include the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if RUBY_PLATFORM =~ /java/ &lt;br /&gt;   require 'rubygems' &lt;br /&gt;   RAILS_CONNECTION_ADAPTERS = %w(jdbcmysql) &lt;br /&gt;   require 'active_record' &lt;br /&gt;   gem 'activerecord-jdbcmysql-adapter' &lt;br /&gt;   require 'active_record/connection_adapters/jdbcmysql_adapter' &lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Insert this immediately preceding the line that looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Rails::Initializer.run do |config|&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; create jboss-web.xml&lt;/h4&gt;&lt;br /&gt;I wanted to create a configuration that takes advantage of JBoss' connection pools for connections to MySQL, unfortunately (dirty secret), I haven't gotten it to work yet. Soooo, you can consider this step optional. Once I figure out what piece is missing to get JNDI DataSource access working, however, this piece &lt;em&gt;will&lt;/em&gt; certainly be needed, so, take it or leave it :)&lt;br /&gt;&lt;br /&gt;The jboss-web.xml maps an application-local resource-ref to a global JNDI name. Typically used to map a 'generic' JNDI ref such as &lt;strong&gt;jdbc/rails&lt;/strong&gt; to a specific ref, such as &lt;strong&gt;jdbc/my_cool_apps/app1&lt;/strong&gt;. Of course, you &lt;em&gt;could&lt;/em&gt; just use &lt;strong&gt;jdbc/my_cool_apps/app1&lt;/strong&gt;, but the thinking is that a level of indirection helps when you need to change things - you just change a config at the container level and don't need to muck about with the app (repackaging/redeploying/etc.). Again, YMMV, take it or leave it.&lt;br /&gt;&lt;br /&gt;Here it is:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt; &lt;br /&gt;&amp;lt;jboss-web&amp;gt; &lt;br /&gt;  &amp;lt;resource-ref&amp;gt; &lt;br /&gt;    &amp;lt;res-ref-name&amp;gt;jdbc/rails&amp;lt;/res-ref-name&amp;gt; &lt;br /&gt;    &amp;lt;jndi-name&amp;gt;jdbc/my_cool_apps/app1&amp;lt;/jndi-name&amp;gt; &lt;br /&gt;  &amp;lt;/resource-ref&amp;gt; &lt;br /&gt;&amp;lt;/jboss-web&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; create -ds.xml file&lt;/h4&gt;&lt;br /&gt;Now that you've mapped the &lt;em&gt;local&lt;/em&gt; JNDI name to the &lt;em&gt;global&lt;/em&gt; JNDI name, you should probably setup the configuration in JBoss that &lt;em&gt;creates&lt;/em&gt; the global JNDI name. Here it is (substitute in your own parameters):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;ISO-8859-1&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;datasources&amp;gt; &lt;br /&gt;  &amp;lt;local-tx-datasource&amp;gt; &lt;br /&gt; &lt;br /&gt;    &amp;lt;jndi-name&amp;gt;jdbc/my_cool_apps/app1&amp;lt;/jndi-name&amp;gt; &lt;br /&gt; &lt;br /&gt;    &amp;lt;connection-url&amp;gt;jdbc:mysql://mysql.example.com:3306/mydb&amp;lt;/connection-url&amp;gt; &lt;br /&gt;    &amp;lt;driver-class&amp;gt;com.mysql.jdbc.Driver&amp;lt;/driver-class&amp;gt; &lt;br /&gt; &lt;br /&gt;    &amp;lt;user-name&amp;gt;my_username&amp;lt;/user-name&amp;gt; &lt;br /&gt;    &amp;lt;password&amp;gt;secret&amp;lt;/password&amp;gt; &lt;br /&gt; &lt;br /&gt;    &amp;lt;!-- Typemapping for JBoss 4.0 --&amp;gt; &lt;br /&gt;    &amp;lt;metadata&amp;gt; &lt;br /&gt;      &amp;lt;type-mapping&amp;gt;mySQL&amp;lt;/type-mapping&amp;gt; &lt;br /&gt;    &amp;lt;/metadata&amp;gt; &lt;br /&gt; &lt;br /&gt;  &amp;lt;/local-tx-datasource&amp;gt; &lt;br /&gt;&amp;lt;/datasources&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This by far isn't the most sophisticated DataSource you can configure, but there are better references elsewhere for the options available.&lt;br /&gt;&lt;br /&gt;This gets dropped in the JBoss application server's "deploy" directory to setup the DataSource in global JNDI.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; create warble.rb&lt;/h4&gt;&lt;br /&gt;Alright, back to the app. Let's create the warble config file, mostly run on defaults, but we need a couple customizations.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ jruby -S warble config&lt;/pre&gt;&lt;br /&gt;-OR-&lt;br /&gt;&lt;pre&gt;$ script/generate warble&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I had some issues with the latter, can't remember if that was before I figured out I needed to &lt;strong&gt;freeze&lt;/strong&gt;, but the first way worked for me, YMMV.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; update warble.rb&lt;/h4&gt;&lt;br /&gt;Documentation for warbler contains oodles of information on configuring, I found no fault with that information. Here's what I did:&lt;br /&gt;&lt;br /&gt;Added&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;config.includes = FileList["jboss-web.xml"]&lt;br /&gt;config.gems += ["activerecord-jdbcmysql-adapter"]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Set &lt;br /&gt;&lt;pre&gt;config.gems["rails"] = "1.1.4"&lt;/pre&gt;&lt;br /&gt;(use whatever version suits you)&lt;br /&gt;&lt;br /&gt;Uncommented&lt;br /&gt;&lt;pre&gt;config.webxml.jndi = 'jdbc/rails'&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's it!&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; update database.yml -- copy production: block&lt;/h4&gt;&lt;br /&gt;So, here's where, if the world were a happy place, I'd tell you how to configure database.yml to use JNDI. Unfortunately, following the available documentation, I haven't gotten this to work. So, instead, I'll show you how to switch to use the 'jdbcmysql' adapter, instead of the 'mysql' adapter.&lt;br /&gt;&lt;br /&gt;Change&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;adapter: mysql&lt;/pre&gt;&lt;br /&gt;To&lt;br /&gt;&lt;pre&gt;adapter: jdbcmysql&lt;/pre&gt;&lt;br /&gt;Painful, I know. You'll need to use a &lt;em&gt;host:&lt;/em&gt; parameter, too, JDBC doesn't connect to /tmp/mysql.sock.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; update new/thankyou.rhtml (change absolute links)&lt;/h4&gt;&lt;br /&gt;Not sure this applies to everyone, by my .rhtml files had absolute references in them to static resources. That needs to change to use relative paths that resolve to within your application. Just removing the leading '/' did the trick for me.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; add close_connections.rb&lt;/h4&gt;&lt;br /&gt;This may be an optional step, I think its only needed if you &lt;strong&gt;do&lt;/strong&gt; use JNDI (not in use here, yet). In any case, you'll want to add an &lt;em&gt;initializers/close_connections.rb&lt;/em&gt; to &lt;em&gt;config&lt;/em&gt; in your app. Contents:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if defined?($servlet_context)&lt;br /&gt;  require 'action_controller/dispatcher'&lt;br /&gt;    ActionController::Dispatcher.after_dispatch do&lt;br /&gt;    ActiveRecord::Base.clear_active_connections!&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt; edit new_rails_defaults.rb&lt;/h4&gt;&lt;br /&gt;Finally (are you still reading?!), the &lt;em&gt;spec&lt;/em&gt; for warbler uses a Rails 2.x (I think) JSON config, this needs to be commented out. Find your &lt;em&gt;new_rails_defaults.rb&lt;/em&gt; under &lt;em&gt;vendor/plugins/warbler-0.9.13&lt;/em&gt; (version may vary), and comment out the last line.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#ActiveSupport.escape_html_entities_in_json = false&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's it!! Seriously.&lt;br /&gt;&lt;br /&gt;Use a line like this to package/repackage/deploy your .WAR and enjoy.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;rake war:clean; rake war; \&lt;br /&gt;if [ -e &amp;lt;rails_app&amp;gt;.war ]; then &lt;br /&gt;unzip -q -o -d $JBOSS_HOME/server/default/deploy/&amp;lt;rails_app&amp;gt;.new &amp;lt;rails_app&amp;gt;.war; &lt;br /&gt;mv $JBOSS_HOME/server/default/deploy/&amp;lt;rails_app&amp;gt;.war $JBOSS_HOME/server/default/deploy/&amp;lt;rails_app&amp;gt;.old; &lt;br /&gt;mv $JBOSS_HOME/server/default/deploy/&amp;lt;rails_app&amp;gt;.new $JBOSS_HOME/server/default/deploy/&amp;lt;rails_app&amp;gt;.war; &lt;br /&gt;rm -rf $JBOSS_HOME/server/default/deploy/&amp;lt;rails_app&amp;gt;.old ; &lt;br /&gt;fi&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Where &amp;lt;rails_app&amp;gt; is your app name; $JBOSS_HOME is set to your JBoss install dir. &lt;strong&gt;BEWARE&lt;/strong&gt; - I chased my tail AROUND AND AROUND because I didn't realize that (a) &lt;em&gt;rake war&lt;/em&gt; doesn't clean tmp/war before setting up &amp; repackaging the WAR, so if you're trying to fix things, your old stuff may still be around; similarly, unless you're deploying the packaged WAR file, JBoss doesn't do you any favors and you should remove the exploded WAR before placing your fresh WAR dir in the deploy dir.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-1469486326580291854?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/1469486326580291854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=1469486326580291854' title='41 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/1469486326580291854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/1469486326580291854'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2009/06/packaging-rails-11-app-for-jruby.html' title='Packaging a Rails 1.1 app for JRuby'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>41</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-4170725105595448028</id><published>2008-03-06T04:59:00.000-08:00</published><updated>2008-12-11T05:09:53.980-08:00</updated><title type='text'>Iditarod GPS in Google Earth</title><content type='html'>First, let me describe myself as a "rookie" fan. My wife got interested in &lt;span style="font-weight: bold; font-style: italic;"&gt;the last great race&lt;/span&gt; last year (2007) [&lt;span style="font-style: italic;"&gt;edit(3/6 9:33AM)&lt;/span&gt; &lt;span style="font-size:85%;"&gt;my wife has been interested for several years, but only recently has technology allowed us to keep up-to-date on the race from afar, instead of waiting for coverage months later&lt;/span&gt;], but for me, it all started this year. My wife and I have gotten to know a family in Alaska this year, the &lt;a href="http://www.mushingdogs.com/"&gt;Holt's&lt;/a&gt;, through my &lt;a href="http://mominmadison.blogspot.com/"&gt;wife&lt;/a&gt;'s &lt;a href="http://cookeatthink.blogspot.com/"&gt;blogs&lt;/a&gt; and overlapping interests. Well, it turns out that &lt;a href="http://www.iditarod.com/race/musherprofiles/musherbio_286.html"&gt;Rick Holt&lt;/a&gt; is a rookie in the &lt;a href="http://www.iditarod.com/"&gt;2008 Iditarod&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;That piqued my tepid interest in the Iditarod to what I'd conservatively call a &lt;span style="font-weight: bold;"&gt;&lt;span style="font-style: italic;"&gt;fury&lt;/span&gt;&lt;/span&gt;. Double that when my wife informed me that, for the first time, the Iditarod would provide &lt;a href="http://race.ionearth.com/iditarod/"&gt;GPS tracking&lt;/a&gt; of some of the mushers (a trial). Oh, and Rick would have one of the GPS devices. SWEET.&lt;br /&gt;&lt;br /&gt;So, my interest is piqued and I'm excited about tracking Rick's progress against the other GPS-enabled mushers, as well as his overall standings (currently 44th after an overnight push through McGrath into Takotna, COOL!). But, I'm underwhelmed with the &lt;a href="http://race.ionearth.com/iditarod/"&gt;Microsoft Virtual Earth&lt;/a&gt; mapping of the mushers and the course. My first thought is to see if I can re-use the data being fed to Microsoft Virtual Earth, to feed into Google Maps, but as I'm working on that, my wife finds &lt;a href="http://www.earthslot.org/iditarod/"&gt;EarthSlot&lt;/a&gt;, which brings together the &lt;a href="http://www.arsc.edu/"&gt;Arctic Regions Supercomputing Center&lt;/a&gt; and the &lt;a href="http://www.gina.alaska.edu/"&gt;Geographical Information Network of Alaska&lt;/a&gt; to provide a &lt;a href="http://code.google.com/apis/kml/documentation/"&gt;KML&lt;/a&gt; feed of the musher's current standings using the GIS data format used by Google Earth.&lt;br /&gt;&lt;br /&gt;Well, that's cool - the KML feed has tons of information, but I thought I could do better. I figured that with the information from IonEarth, I should be able to map the GPS near-realtime location of the GPS-enabled mushers into &lt;a href="http://earth.google.com/"&gt;Google Earth&lt;/a&gt;, with all the stats available in the Microsoft Virtual Earth mapping.&lt;br /&gt;&lt;br /&gt;And I did. &lt;a href="http://bricedruth.name/iditarod.kml"&gt;Click here&lt;/a&gt; to download the KML with a self-refreshing link to the latest near-realtime data provided by IonEarth, translated by a script to KML. I've also enhanced the original EarthSlot KML with a network link to &lt;a href="http://www.srh.noaa.gov/ridge/kmzgenerator.php"&gt;National Weather Service / NOAA weather radar aggregation for Alaska&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Cw0gWV4SWAA/R8_yimDgVkI/AAAAAAAAAQ0/0v7aMstCorA/s1600-h/earth1.png"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_Cw0gWV4SWAA/R8_yimDgVkI/AAAAAAAAAQ0/0v7aMstCorA/s320/earth1.png" alt="" id="BLOGGER_PHOTO_ID_5174621173016712770" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Pulling this data into Google Earth provides a few interesting benefits.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Google Earth provides better aerial / terrain data for the course than Microsoft Virtual Earth (this is subjective, I suppose)&lt;/li&gt;&lt;li&gt;The data feed I provide gives Google Earth information so when you double-click on a musher's sled icon, Google Earth will rotate your map view to correspond with the musher's current heading. [this was useful when Rick was heading into Nikolai, from the course / GPS, it looked like he was off course, but rotating the map view to his current heading showed he was heading straight into the checkpoint!]&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Cw0gWV4SWAA/R8_zMmDgVlI/AAAAAAAAAQ8/wBsIQd08hkA/s1600-h/earth2.png"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_Cw0gWV4SWAA/R8_zMmDgVlI/AAAAAAAAAQ8/wBsIQd08hkA/s320/earth2.png" alt="" id="BLOGGER_PHOTO_ID_5174621894571218514" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-style: italic;"&gt;Map is aligned with Ken Anderson's current heading&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Google Earth has a Ruler. Open the Ruler tool and click on your favorite GPS-enabled musher and anywhere else on the map (next musher, next checkpoint, whatever) and get a very accurate estimate of the distance (in feet, miles, etc.)&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Cw0gWV4SWAA/R8_z_GDgVmI/AAAAAAAAARE/6A3nWUTEA5M/s1600-h/earth3.png"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_Cw0gWV4SWAA/R8_z_GDgVmI/AAAAAAAAARE/6A3nWUTEA5M/s320/earth3.png" alt="" id="BLOGGER_PHOTO_ID_5174622762154612322" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Google Earth imports information from &lt;a href="http://www.panoramio.com/"&gt;Panoramio &lt;/a&gt;which includes pictures folks have taken at the various checkpoints (may be from this year or previous years). Information from wikipedia on certain locations (e.g. Takotna, Nikolai, Mcgrath) is also available right in Google Earth.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Cw0gWV4SWAA/R8_0o2DgVnI/AAAAAAAAARM/PWCCdmcATjg/s1600-h/earth4.png"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_Cw0gWV4SWAA/R8_0o2DgVnI/AAAAAAAAARM/PWCCdmcATjg/s320/earth4.png" alt="" id="BLOGGER_PHOTO_ID_5174623479414150770" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The weather radar overlay from the National Weather Service is just SO FREAKIN' COOL!&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Cw0gWV4SWAA/R8_1KGDgVoI/AAAAAAAAARU/XMLhEKvmwoI/s1600-h/earth5.png"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_Cw0gWV4SWAA/R8_1KGDgVoI/AAAAAAAAARU/XMLhEKvmwoI/s320/earth5.png" alt="" id="BLOGGER_PHOTO_ID_5174624050644801154" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-style: italic;"&gt;Weather around current position of mushers seems clear, but there's a big storm rolling through ahead.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;The added indirection between the Google Earth feed and the IonEarth data that my feed script provides, also allows some throttling of the upstream requests. That isn't possible when just using Ajax in a browser to the primary data source. My script refreshes the data from IonEarth once every 10 minutes, max. Within that timeframe, it serves up the KML to Google Earth with cached GPS data from IonEarth. [Edit 3/6/08]: I've been asked (politely) to reduce the refresh rate to once an hour]&lt;br /&gt;&lt;br /&gt;I'll publish a post soon on the details of the script that takes the IonEarth data and transforms it into KML.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-4170725105595448028?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/4170725105595448028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=4170725105595448028' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/4170725105595448028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/4170725105595448028'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2008/03/iditarod-gps-in-google-earth.html' title='Iditarod GPS in Google Earth'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Cw0gWV4SWAA/R8_yimDgVkI/AAAAAAAAAQ0/0v7aMstCorA/s72-c/earth1.png' height='72' width='72'/><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-5853409003983234930</id><published>2008-01-02T07:01:00.000-08:00</published><updated>2008-01-02T07:12:24.897-08:00</updated><title type='text'>Computers: planned obsolescense, what can be done?</title><content type='html'>This morning, my wife showed me the &lt;a href="http://www.storyofstuff.com/"&gt;Story of Stuff&lt;/a&gt;. The "&lt;span style="font-style: italic;"&gt;Story of Stuff&lt;/span&gt;," with Annie Leonard, is a discussion of extraction, manufacturing, distribution, consumption, waste and more. This is an amazingly put together flash video (about 20m) and at one point it squarely points the finger at computers with "planned obsolescense" and "perceived obsolescense." Specifically, the inability to upgrade many (most?) computers that folks have these days. If the next new thing comes out (&lt;a href="http://www.microsoft.com/windows/%20products/windowsvista/default.mspx"&gt;Vista&lt;/a&gt;, even &lt;a href="http://www.apple.com/macosx/"&gt;OS X Leopard&lt;/a&gt;) - its time to buy a new computer and chuck &lt;span style="font-weight: bold;"&gt;everything&lt;/span&gt; you had before?! Is this necessary?! Sure, for some of us, we can upgrade certain things ... add memory, etc. But industrial design of computers isn't &lt;span style="font-style: italic;"&gt;designed&lt;/span&gt; to be upgraded. And with the type of &lt;a href="http://www.apple.com/imac/"&gt;innovative&lt;/a&gt;, &lt;a href="http://www.apple.com/iphone/"&gt;awesome&lt;/a&gt; &lt;a href="http://www.apple.com/ipodclassic/"&gt;designs&lt;/a&gt; we see from companies like &lt;a href="http://www.apple.com"&gt;Apple&lt;/a&gt;, you can't tell me this isn't possible.&lt;br /&gt;&lt;br /&gt;So, go watch this, then comment below - what can be done to put computers, software, etc. into a sustainable, green chemistry cycle? What's being done already? Where should conscientious consumers be putting their $$?&lt;br /&gt;&lt;br /&gt;Thanks!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-5853409003983234930?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/5853409003983234930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=5853409003983234930' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/5853409003983234930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/5853409003983234930'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2008/01/computers-planned-obsolescense-what-can.html' title='Computers: planned obsolescense, what can be done?'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-4645011438904243511</id><published>2007-11-16T21:19:00.001-08:00</published><updated>2007-11-16T21:23:51.946-08:00</updated><title type='text'>At No Fluff Just Stuff Chicago</title><content type='html'>Arrived at &lt;a href="http://www.nofluffjuststuff.com/conference/chicago/2007/11/index.html"&gt;NFJS Chicago&lt;/a&gt; today and promptly jumped into the afternoon sessions. I'll be trying to post information I'm finding interesting as I come across it and I've already put up two posts. Where? Well - on the new &lt;a href="http://bricedruth.name/Site/Coding/Coding.html"&gt;Coding blog&lt;/a&gt; I started in my iWeb site. The first post is on &lt;a href="http://bricedruth.name/Site/Coding/Entries/2007/11/16_Enterprise_Performance_%26_Scalability.html"&gt;Enterprise Performance &amp;amp; Scalability&lt;/a&gt;. The second is on &lt;a href="http://bricedruth.name/Site/Coding/Entries/2007/11/16_Domain_Driven_Design.html"&gt;Domain Driven Design&lt;/a&gt; and how to build the ubiquitous language in your team.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Still need to blog about &lt;a href="http://www.nofluffjuststuff.com/speaker_topic_view.jsp?topicId=413"&gt;monitoring your applications&lt;/a&gt;, but that will come tomorrow, I'm afraid.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enjoy!&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-4645011438904243511?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/4645011438904243511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=4645011438904243511' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/4645011438904243511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/4645011438904243511'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2007/11/at-no-fluff-just-stuff-chicago.html' title='At No Fluff Just Stuff Chicago'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-6775496138453631198</id><published>2007-10-31T20:36:00.000-07:00</published><updated>2007-10-31T20:41:25.544-07:00</updated><title type='text'>IP Aliasing on Leopard</title><content type='html'>I just added &lt;a href="http://bricedruth.name/Site/Get_er_done/Get_er_done.html"&gt;a new blog&lt;/a&gt; in my iWeb site on tips/tricks I use to be productive. The first post is about &lt;a href="http://bricedruth.name/Site/Get_er_done/Entries/2007/10/31_IP_Aliasing_on_Mac_OS_X_Leopard.html"&gt;IP Aliasing on Leopard&lt;/a&gt;, something I am using to run multiple instances of &lt;a href="http://labs.jboss.com/jbossas/"&gt;JBoss AS&lt;/a&gt;. This makes a nice environment to test the &lt;a href="http://labs.jboss.com/jbosstm/resources/product_overview/wst.html"&gt;Web Services Transactions&lt;/a&gt; (XTS) module from&lt;a href="http://labs.jboss.com/jbosstm/"&gt; JBoss Transactions&lt;/a&gt; (JBossTS).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-6775496138453631198?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/6775496138453631198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=6775496138453631198' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/6775496138453631198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/6775496138453631198'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2007/10/ip-aliasing-on-leopard.html' title='IP Aliasing on Leopard'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-6835373154794795573</id><published>2007-10-27T18:57:00.000-07:00</published><updated>2007-10-27T19:23:58.890-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='intel'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='64bit'/><category scheme='http://www.blogger.com/atom/ns#' term='leopard'/><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>Eclipse on Leopard: fine. 64-bit? Not so fine.</title><content type='html'>&lt;p&gt;I know I'm a late adopter and all, but I thought I'd provide some information on Eclipse on OS X Leopard. First off: it runs fine. Many of the concerns were that 64-bit Java would break Eclipse because of the SWT/Carbon underpinnings, which are 32-bit, as I understand it.&lt;/p&gt;&lt;p&gt;Well, rest easy - as it does with many new technologies, Apple has left full backwards compatibility in place. It appears that Java runs in 32-bit mode by default, so basically everything that worked previously (including SWT) will continue to work.&lt;/p&gt;&lt;p&gt;So what about Eclipse on 64-bit Java? Yeah, it doesn't work. So - to all those that predicted this, kudos. You got it right. Adding "-d64" is the flag that tells the JVM to run in 64-bit mode - and adding this to eclipse.ini "-vmargs" causes an exception when SWT is loaded.&lt;/p&gt;&lt;p&gt;Want to test if you can run 64-bit Java? Here's what to do. In Terminal, run the following command:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Commands/java -d64 -Xmx2560M -version&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Running this should output something like so:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;java version "1.5.0_13"&lt;br /&gt;Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_13-b05-237)&lt;br /&gt;Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_13-119, mixed mode)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;If you don't get this, or get some type of message like "Cannot run Java in 64 bit mode. Continuing in 32 bit mode." then you  may not have a 64-bit chipset. Notably, the PPC chips (while G5s are 64-bit) &lt;a href="http://lists.apple.com/archives/Java-dev/2007/Oct/msg00258.html"&gt;cannot run 64-bit Java&lt;/a&gt;). Further, the first generation of Intel chips released by Apple, &lt;a href="http://en.wikipedia.org/wiki/Intel_Core"&gt;Duo Core&lt;/a&gt;, are not 64-bit. Only the Core 2 Duo (and later) chips are 64-bit. Finally - if you ran the "-d64" test by just specifying "java" on the command line, instead of the full path - you may be running into &lt;a href="http://lists.apple.com/archives/Java-dev/2007/Oct/msg00270.html"&gt;a bug that was discovered too late to be fixed in GM&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I'll give a shot at running 64-bit Java from within Eclipse (say, to run JBoss AS - that should work). I'll report back with results!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-6835373154794795573?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/6835373154794795573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=6835373154794795573' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/6835373154794795573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/6835373154794795573'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2007/10/eclipse-on-leopard-fine-64-bit-not-so.html' title='Eclipse on Leopard: fine. 64-bit? Not so fine.'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-7269012074559419974</id><published>2007-10-21T20:06:00.000-07:00</published><updated>2007-10-21T20:10:29.482-07:00</updated><title type='text'>Locavore in training.</title><content type='html'>To document and track my ongoing efforts to become more of a &lt;a href="http://en.wikipedia.org/wiki/Locavore"&gt;Locavore&lt;/a&gt; with my family, I have started a &lt;a href="http://bricedruth.name/Site/Locavore/Locavore.html"&gt;new blog&lt;/a&gt; on my new iWeb &lt;a href="http://bricedruth.name/"&gt;site&lt;/a&gt;. I have a few things up there already (and am liking how easy it is to layout photos in iWeb, sweet!). I hope to keep things up-to-date, though this Locavore family might run into harder straights with winter coming on and the harvest nearing completion.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Though that in itself should provide ample material to blog about! Enjoy.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-7269012074559419974?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/7269012074559419974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=7269012074559419974' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/7269012074559419974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/7269012074559419974'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2007/10/locavore-in-training.html' title='Locavore in training.'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-9157348456895579008</id><published>2007-10-21T19:59:00.001-07:00</published><updated>2007-10-21T20:05:39.151-07:00</updated><title type='text'>New blog!</title><content type='html'>I have started a &lt;a href="http://bricedruth.name/Site/Requirements_Engineering/Requirements_Engineering.html"&gt;new blog&lt;/a&gt;, mostly to evaluate the &lt;a href="http://www.apple.com/ilife/iweb/"&gt;iWeb '08&lt;/a&gt; software that's part of the &lt;a href="http://www.apple.com/ilife/"&gt;iLife '08&lt;/a&gt; suite from &lt;a href="http://www.apple.com/"&gt;Apple&lt;/a&gt;. As part of my "&lt;a href="http://bricedruth.name/"&gt;Site&lt;/a&gt;" in iWeb, this blog will focus on thoughts and insights I have in the field of &lt;a href="http://en.wikipedia.org/wiki/Requirements_engineering"&gt;requirements engineering (RE)&lt;/a&gt;. While most of my day-to-day activities don't focus 100% on this field, in my current position, I do deal with this on an ongoing basis, helping the business better communicate their needs, formulate what features the software should provide, and if needed, expand on those features in &lt;a href="http://en.wikipedia.org/wiki/Use_case"&gt;use case&lt;/a&gt; specifications.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, topics related to RE will be the focus of this new iWeb blog. Enjoy!&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-9157348456895579008?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/9157348456895579008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=9157348456895579008' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/9157348456895579008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/9157348456895579008'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2007/10/new-blog.html' title='New blog!'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-2721674604117952508</id><published>2007-09-24T14:19:00.000-07:00</published><updated>2007-09-24T22:09:16.416-07:00</updated><title type='text'>EasyMock testing: isolating methods with partial mocks</title><content type='html'>Today I was faced with testing a method that presented two difficulties. First, the method under test was overriding a superclass method and invoking the superclass' same-named method. Second, the method needed to invoke an unavoidable static method on a utility class. I managed to work around both difficulties with essentially the same approach, instead of invoking the difficult to mock methods directly (super.whatever() and Utility.staticMethod()), delegate to a helper method, which can then be mocked with a partial mock.&lt;br /&gt;&lt;br /&gt;Here are the details.&lt;br /&gt;&lt;br /&gt;The method under test overrides getAction(ActionContext context, String type, ActionConfig actionConfig).&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    @Override&lt;br /&gt;protected synchronized Action getAction(ActionContext context, String type, ActionConfig actionConfig) throws Exception { // NOPMD&lt;br /&gt;Action action = &lt;b style="background: yellow none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;super.getAction(context, type, actionConfig);&lt;/b&gt;&lt;br /&gt;Class actionClass = action.getClass();&lt;br /&gt;Method[] methods = actionClass.getMethods();&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Determine if methods exist that need to be injected with&lt;br /&gt;* beans from the ApplicationContext.&lt;br /&gt;*/&lt;br /&gt;for (Method method : methods) {&lt;br /&gt;   if (method.isAnnotationPresent(InjectBean.class)) {&lt;br /&gt;       InjectingCreateAction.LOG.info("Found annotation on: " + actionClass.getName());&lt;br /&gt;       Class&amp;lt; ? &amp;gt; clazz = method.getParameterTypes()[0];&lt;br /&gt;       Object bean = &lt;b style="background: yellow none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;ApplicationContextUtils.getBean(clazz);&lt;/b&gt;&lt;br /&gt;       method.invoke(action, new Object[] { bean }); // NOPMD&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;return action;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The two methods presenting some difficulties are highlighted in yellow. A straightforward &lt;a href="http://www.easymock.org/"&gt;EasyMock&lt;/a&gt; test of this method would fail on these two methods, unless they were run in an environment where these methods could successfully execute. Since the class extends &lt;a href="http://struts.apache.org/1.3.8/index.html"&gt;Struts&lt;/a&gt;' &lt;a href="http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/CreateAction.java?view=annotate"&gt;CreateAction&lt;/a&gt; to inject dependencies on Action classes, calling super.getAction() would require all the necessary Struts pieces to be in place when this unit test runs. That's more than we need to test this functionality.&lt;br /&gt;&lt;br /&gt;Using EasyMock's &lt;a href="http://www.easymock.org/EasyMock2_2_2_ClassExtension_Documentation.html"&gt;class extension 2.2.2+&lt;/a&gt;, we can create a partial mock of the class under test, and use this with some simple refactoring to isolate this method to make it testable.&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    @Override&lt;br /&gt;protected synchronized Action getAction(ActionContext context, String type, ActionConfig actionConfig) throws Exception { // NOPMD&lt;br /&gt;   Action action = &lt;b style="background: yellow none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;getActionObject(context, type, actionConfig);&lt;/b&gt;&lt;br /&gt;   Class actionClass = action.getClass();&lt;br /&gt;   Method[] methods = actionClass.getMethods();&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Determine if methods exist that need to be injected with&lt;br /&gt;    * beans from the ApplicationContext.&lt;br /&gt;    */&lt;br /&gt;   for (Method method : methods) {&lt;br /&gt;       if (method.isAnnotationPresent(InjectBean.class)) {&lt;br /&gt;           InjectingCreateAction.LOG.info("Found annotation on: " + actionClass.getName());&lt;br /&gt;           Class&amp;lt; ? &amp;gt; clazz = method.getParameterTypes()[0];&lt;br /&gt;           Object bean = &lt;b style="background: yellow none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;getBean(clazz);&lt;/b&gt;&lt;br /&gt;           method.invoke(action, new Object[] { bean }); // NOPMD&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return action;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Delegate method to allow for mock testing of getAction method, which would&lt;br /&gt;* otherwise call a static method on {@link ApplicationContextUtils}.&lt;br /&gt;* @param &amp;lt;T&amp;gt; the class of the return object (inferred)&lt;br /&gt;* @param clazz the class of the requested object (explicit)&lt;br /&gt;* @return an object from the ApplicationContext matching clazz&lt;br /&gt;*/&lt;br /&gt;public &amp;lt;T&amp;gt; T getBean(Class&amp;lt;T&amp;gt; clazz) {&lt;br /&gt;   return ApplicationContextUtils.getBean(clazz);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Delegate method to allow for mock testing of getAction method which overrides&lt;br /&gt;* {@link CreateAction#getAction(ActionContext, String, ActionConfig)}.&lt;br /&gt;* @param context ActionContext&lt;br /&gt;* @param type String&lt;br /&gt;* @param actionConfig ActionConfig&lt;br /&gt;* @return The configured Action object&lt;br /&gt;* @throws Exception pass-through&lt;br /&gt;*/&lt;br /&gt;public Action getActionObject(ActionContext context, String type, ActionConfig actionConfig) throws Exception { // NOPMD&lt;br /&gt;   return super.getAction(context, type, actionConfig);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;We have created two delegate methods to do the dirty work of invoking the static method and calling the super class method. Here's how we put that to use with a partial mock.&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    public void testGetAction() throws Exception {&lt;br /&gt;     InjectingCreateAction partialMock =&lt;br /&gt;         EasyMock.createMock(InjectingCreateAction.class,&lt;br /&gt;                 &lt;b style="background: yellow none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;new Method[] {&lt;br /&gt;             InjectingCreateAction.class.getMethod("getActionObject",&lt;br /&gt;                     ActionContext.class,&lt;br /&gt;                     String.class,&lt;br /&gt;                     ActionConfig.class),&lt;br /&gt;             InjectingCreateAction.class.getMethod("getBean",&lt;br /&gt;                     Class.class),&lt;/b&gt;&lt;br /&gt;         });&lt;br /&gt;  &lt;br /&gt;     IWorkflowController bean = EasyMock.createMock(IWorkflowController.class);&lt;br /&gt;     SmokeTestAction test = new SmokeTestAction();&lt;br /&gt;     EasyMock.expect(partialMock.getActionObject(&lt;br /&gt;             (ActionContext) EasyMock.anyObject(),&lt;br /&gt;             (String) EasyMock.anyObject(),&lt;br /&gt;             (ActionConfig) EasyMock.anyObject())).andReturn(test);&lt;br /&gt;     EasyMock.expect(partialMock.getBean(IWorkflowController.class))&lt;br /&gt;         .andReturn(bean);&lt;br /&gt;  &lt;br /&gt;     test.setWfService(bean);&lt;br /&gt;  &lt;br /&gt;     EasyMock.replay(partialMock);&lt;br /&gt;     EasyMock.replay(bean);&lt;br /&gt;  &lt;br /&gt;     Action action = partialMock.getAction(null, null, null);&lt;br /&gt;     assertNotNull(action);&lt;br /&gt;     EasyMock.verify(partialMock);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Creating the EasyMock with an array of Methods tells EasyMock to only mock these methods, not the entire class. The remaining calls are passed through to the underlying class. The remainder of the test is standard EasyMock stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-2721674604117952508?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/2721674604117952508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=2721674604117952508' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/2721674604117952508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/2721674604117952508'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2007/09/easymock-testing-isolating-methods-with.html' title='EasyMock testing: isolating methods with partial mocks'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-997314904620243111</id><published>2007-09-06T20:53:00.000-07:00</published><updated>2008-12-11T05:09:54.835-08:00</updated><title type='text'>ZopeEditManager, Safari, automation</title><content type='html'>Since Safari 3 debuted, I have been using Safari in lieu of Firefox, more and more. One feature I've missed is Firefox' ability to associate the ExternalEdit files from Plone with the ZopeEditManager. Click on the pencil, and voila, you're editing locally.&lt;div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;img src="http://4.bp.blogspot.com/_Cw0gWV4SWAA/RuDMYjtvQoI/AAAAAAAAAPI/XJV0emutt3Y/s320/Picture+1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5107306699714151042" /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, I've finally figured out what to do to get this linked up in Safari. Enter &lt;a href="http://www.apple.com/macosx/features/automator/"&gt;Automator&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;img src="http://images.apple.com/macosx/features/automator/images/indextop20050412.jpg" border="0" alt="" /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And if you're a Mac user like myself, it won't come as a surprise that it was actually quite easy.&lt;/div&gt;&lt;div&gt;&lt;ol id=""&gt;&lt;li&gt;Launch Automator. You'll see a couple panes on the left (drag-src) and a pane on the right (drag-target).&lt;/li&gt;&lt;li&gt;Your first workflow step will be Find Finder Items (the search box, top left, is a convenient way to find the workflow steps). &lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_Cw0gWV4SWAA/RuDPkjtvQpI/AAAAAAAAAPQ/ZdkVnuqOXfE/s320/Picture+2.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5107310204407464594" /&gt;&lt;/li&gt;&lt;li&gt;Select the folder where Safari will drop the .zem files (Desktop, in my case)&lt;/li&gt;&lt;li&gt;Select "Name", "Ends with", and ".zem" for the criteria.&lt;/li&gt;&lt;li&gt;Add the final criteria (yep, already on the last one!) - Open Finder Items.&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_Cw0gWV4SWAA/RuDQpTtvQqI/AAAAAAAAAPY/UtHe1-eEFQc/s320/Picture+3.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5107311385523471010" /&gt; &lt;/li&gt;&lt;li&gt;Nothing to configure on this workflow step, the default "Open with: Default Application" suits us just fine (note: if ZopeEditManager isn't associated with .zem files on your system, select ZopeEditManager in this drop-down).&lt;/li&gt;&lt;li&gt;Almost done. Save your workflow as a "Folder Action" plugin. File ~ Save As Plug-in...&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_Cw0gWV4SWAA/RuDRaDtvQrI/AAAAAAAAAPg/PLzIk4uEBO4/s320/Picture+4.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5107312223042093746" /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Attached to Folder:&lt;/span&gt; should be the folder you selected in your first workflow step.&lt;/li&gt;&lt;li&gt;Ctrl-click (i.e. right-click) on the folder you're targeting, select "Enable Folder Actions" if this is the first time you're using , Folder Actions on your system.&lt;/li&gt;&lt;li&gt;Ctrl-click on the folder you're targeting, select &lt;span class="Apple-style-span" style="font-style: italic;"&gt;Configure Folder Actions ...&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;Click the "+" for the left pane, select your folder (e.g. Desktop)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;Click the "+" for the right pane, select your Automator workflow&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;Close &lt;span class="Apple-style-span" style="font-style: italic;"&gt;Folder Actions Setup&lt;/span&gt;, you're done!&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Test it out by clicking an ExternalEdit link from Safari, should work like a charm.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enjoy!&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-997314904620243111?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/997314904620243111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=997314904620243111' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/997314904620243111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/997314904620243111'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2007/09/zopeeditmanager-safari-automation.html' title='ZopeEditManager, Safari, automation'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Cw0gWV4SWAA/RuDMYjtvQoI/AAAAAAAAAPI/XJV0emutt3Y/s72-c/Picture+1.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-115512948704961752</id><published>2006-08-09T05:50:00.000-07:00</published><updated>2006-08-09T09:47:36.350-07:00</updated><title type='text'>Leopard, Apple not revealing secrets</title><content type='html'>&lt;div class="topic"&gt;apple&lt;/div&gt;In Steve Job's recent keynote, he made a point to tell listeners explicitly that not all of Leopard's features would be revealed, giving the explanation:&lt;br /&gt;&lt;blockquote&gt;We don’t want our friends to start their photocopiers any sooner than they have to.&lt;br /&gt;-Steve Jobs, 2006&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The media has popularly taken "our friends" to mean Microsoft, and for good reason. Banners at Apple's Worldwide Developer's Conference (WWDC) berated the Redmond institution for copying Mac OS X features into Vista and generally failing to innovate.&lt;br /&gt;&lt;br /&gt;A recent &lt;a href="http://www.macworld.com/2006/08/opinion/ihnatko/index.php?lsrc=mwrss"&gt;post&lt;/a&gt; by &lt;a href="http://www.macworld.com/info/contact/form.php?e=Editors&amp;amp;t=e"&gt;Andy Ihnatko&lt;/a&gt; at Macworld speculated that these "secret features" of Leopard might be tied to as yet unannounced hardware, which is certainly possible, even likely. But there's another possibility to consider, one that doesn't necessarily aim squarely at Microsoft's &lt;a href="http://www.microsoft.com/windowsvista/"&gt;Vista&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Consider online services. Apple has made significant investments in the &lt;a href="http://www.apple.com/itunes/music/"&gt;iTunes Music Store&lt;/a&gt; and &lt;a href="http://www.mac.com/"&gt;.Mac&lt;/a&gt;, tieing in the consumer's investment in a Mac and an iPod into a larger online/digital lifestyle. In this arena, &lt;a href="http://www.apple.com/"&gt;Apple&lt;/a&gt; faces stiff competition from &lt;a href="http://www.google.com/"&gt;Google&lt;/a&gt;, &lt;a href="http://www.yahoo.com/"&gt;Yahoo&lt;/a&gt;, and new Web 2.0 properties like &lt;a href="http://www.flickr.com/"&gt;Flickr&lt;/a&gt;, &lt;a href="http://www.youtube.com/"&gt;YouTube&lt;/a&gt;, &lt;a href="http://picasa.google.com/"&gt;Picasa&lt;/a&gt;, &lt;a href="http://www.blogger.com/"&gt;Blogger&lt;/a&gt;, etc. With Apple's &lt;a href="http://www.apple.com/ilife/"&gt;iLife&lt;/a&gt; suite offering "digital life" applications such as &lt;a href="http://www.apple.com/iphoto/"&gt;iPhoto&lt;/a&gt;, &lt;a href="http://www.apple.com/ilife/iweb/"&gt;iWeb&lt;/a&gt;, &lt;a href="http://www.apple.com/ical/"&gt;iCal&lt;/a&gt;, and &lt;a href="http://www.apple.com/imovie/"&gt;iMovie&lt;/a&gt;, it is easy to see how Apple's "friends" are Flickr, Blogger, Google Calendar, and YouTube (respectively).&lt;br /&gt;&lt;br /&gt;Nevermind Microsoft's &lt;a href="http://www.live.com/"&gt;Windows Live&lt;/a&gt;, an online resource/community that the Redmond company will certainly be integrating into Vista when it ships.&lt;br /&gt;&lt;br /&gt;So what kind of integrations, aggregations, and mashups might we see? I don't know, what do you think? Let your imagination loose - what would you like to see Leopard integrate with online, either with Apple's services (iTMS, .Mac) or other popular services. Post to the comments with your ideas.&lt;br /&gt;&lt;br /&gt;Of course, much as Andy wrote, this is all pure speculation, I certainly have no more inside knowledge of what's going on at Apple than Apple's "friends" do. But, for this Apple enthusiast, at least, there's some hope that not all of Leopard's new features will require an additional monetary investment. Here's to hoping.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-115512948704961752?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/115512948704961752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=115512948704961752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115512948704961752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115512948704961752'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2006/08/leopard-apple-not-revealing-secrets.html' title='Leopard, Apple not revealing secrets'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-115335970177531177</id><published>2006-07-19T18:27:00.000-07:00</published><updated>2006-07-19T18:41:41.786-07:00</updated><title type='text'>Referrals in JBoss jBPM</title><content type='html'>JBoss' jBPM doesn't really have any notion of "referring" a Task (TaskInstance). Referring a Task is analagous to an "assist". For example, a worker is assigned a Task, but the details of the Task reveal that the worker needs additional assistance or an "expert opinion" on some aspect of the Task before being able to complete the work.&lt;br /&gt;&lt;br /&gt;Typically in this case, both the original worker and the worker rendering assistance would see the Task in the "inbox" or task list. In jBPM, however, a Task is assigned to only one worker at a time, so how can a referral be handled? One way is to use the jBPM client APIs to create a new Task on-the-fly. Typically Tasks are created when process execution enters a task-node, but jBPM also allows you to create a new Task at run-time.&lt;br /&gt;&lt;br /&gt;For a referral, it may be that the worker rendering assistance doesn't absolutely have to complete the task for process execution to continue, so it might be a good idea to create the new Task with isBlocking set to false. Likewise, for a referral, typically the original worker is still "in control" of the Task, so isSignalling should be false. This means that when the assisting worker completes the Task (TaskInstance.end()), the current Token will not be signalled.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-115335970177531177?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/115335970177531177/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=115335970177531177' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115335970177531177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115335970177531177'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2006/07/referrals-in-jboss-jbpm.html' title='Referrals in JBoss jBPM'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-115328225909618026</id><published>2006-07-18T20:47:00.000-07:00</published><updated>2006-07-18T21:10:59.120-07:00</updated><title type='text'>Recovering from Catastrophe</title><content type='html'>A neighbor recently had a catastrophic hard drive failure in his family's HP Pavilion laptop. These things happens, and they are usually pretty painful, unfortunately. If some foresight existed to make backups, that mitigates some of the pain, but the system still needs to be installed, configured, data restored, etc. In this case, no backups existed. From what I gather, the laptop was taken to a repair shop (&lt;a href="http://www.geeksquad.com/"&gt;Geek Squad&lt;/a&gt; at Bestbuy, or something along those lines) and they replaced the hard drive and installed Windows.&lt;br /&gt;&lt;br /&gt;Upon returning home to start getting things back in order, the first order of business was getting online. Unfortunately, connecting to the wireless network was a no go. Like many folks without IT or I/S in their job description, my neighbor tried a few things without really knowing what the problem might be, but to no avail. The SMC access point had worked fine for two years, so something with the laptop must still be wrong.&lt;br /&gt;&lt;br /&gt;So, this afternoon while standing in the alley watching our kids play, he asked if I had any experience setting up wireless access points. Indeed, I have set up many wireless systems, from a PC-based access point from Linux/Mac/Windows, to Airport, Linksys, Cisco, and Netgear hardware access points.&lt;br /&gt;&lt;br /&gt;So, after the kids were in bed, I headed over. After some initial poking around, I was baffled that XP's network connections control panel didn't even show a wireless network adapter. After getting some of the back-story above, I figured that the repair shop had just installed Windows, but not any of the drivers for the HP Pavilion hardware. HP's site is quite good, so a few clicks later, the wireless adapter was visible in the systray.&lt;br /&gt;&lt;br /&gt;At that point, getting the SMC access point setup again was simple. Note: don't hit the reset button on your hardware unless you really know what you're doing. If you know you're going to have to re-configure your hardware when you hit reset, feel free. If you think hitting reset might get things working again - please refrain. Thankfully, &lt;a href="http://www.amazon.com/"&gt;Amazon&lt;/a&gt; started linking to PDF manuals for many electronics items over the last couple years - so a quick search got us on track for configuring the access point from zero.&lt;br /&gt;&lt;br /&gt;Lesson: most systems these days need special drivers not bundled with Windows, so if a Windows reinstall is just what the doctor ordered, be sure to follow-up with installing your hardware's drivers. Ideally, you can mention this to your repair shop and they'll do what they can do get things setup for you. Also, avoid the reset button in most troubleshooting situations.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-115328225909618026?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/115328225909618026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=115328225909618026' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115328225909618026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115328225909618026'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2006/07/recovering-from-catastrophe.html' title='Recovering from Catastrophe'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-115291709784303544</id><published>2006-07-14T15:41:00.000-07:00</published><updated>2006-07-14T16:03:40.666-07:00</updated><title type='text'>Best design: flexible or simple?</title><content type='html'>Should software be designed for flexibility to meet future needs or should the software be designed as simply as can be, to meet current needs and requirements? I would argue the latter, which probably puts me in the camps of Fowler et al. &lt;br /&gt;&lt;br /&gt;Here's why: if future needs are uncertain, trying to design for future flexibility may well build the software into a cage rather than yielding the desired flexibility. Sure, the software is "flexible" if the future needs match the predicted future needs built into the design.&lt;br /&gt;&lt;br /&gt;On the other hand, if the software is kept simple, meeting the known requirements and designed well (following OO principles and such), when new needs surface, the software can be amended to meet those needs. Since there's been no predetermined design for this new need, this should provide the maximum flexibility.&lt;br /&gt;&lt;br /&gt;This embodies the spirit of iterative, incremental development. Done right, IID should be agile by nature, not by following some certain prescribed agile methodology such as SCRUM or XP. I think many projects quickly grasp iterative development, but incremental development seems a more difficult concept to understand.&lt;br /&gt;&lt;br /&gt;Understand this - if the goal is to predict future needs, with incomplete current understanding, then even if its called "designing for flexibility" - it really is little more than waterfall development. Incremental development isn't just about building the system in stages or phases. It is also about determining the needs, the design, the implementation, and the testing methodology in iterations. Of course, this means the project starts with an incomplete understanding of the details of the final system. That's no fault of IID - that's just the reality of things.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-115291709784303544?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/115291709784303544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=115291709784303544' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115291709784303544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115291709784303544'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2006/07/best-design-flexible-or-simple.html' title='Best design: flexible or simple?'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31053906.post-115276574461685296</id><published>2006-07-12T21:29:00.000-07:00</published><updated>2006-07-12T21:42:24.626-07:00</updated><title type='text'>MVC, as simple as HTML?</title><content type='html'>I recently got to thinking about MVC as it relates to GWT, AJAX, the Web, etc. Of course, there are many MVC(2) frameworks out there - Struts, Webworks, Spring MVC, etc. But, there's a simple MVC, I think.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Model :: XHTML&lt;/li&gt;&lt;li&gt;View :: CSS&lt;/li&gt;&lt;li&gt;Controller :: JavaScript&lt;/li&gt;&lt;/ul&gt;Let's think about this for a second. If XHTML is the model, it contains the state of "system" (the page in this case). If the XHTML is done correctly, it contains only structural/semantic markup, right? No presentation information. This is just the data, and that's the model, pretty simple.&lt;br /&gt;&lt;br /&gt;Now, it makes sense that CSS is the view. It is the presentation of the data. As most people have seen with the &lt;a href="http://www.csszengarden.com/"&gt;CSS Zen Garden&lt;/a&gt;, the CSS can dramatically change the view/presentation of the data. CSS can also do minimal interaction (e.g. :hover). CSS is the view, that seems pretty simple, too.&lt;br /&gt;&lt;br /&gt;Now the controller. JavaScript? Yep, I think so. If by JavaScript we take into account the browser itself, JavaScript is "observing" the view by monitoring mouse movements (onhover,  onblur, etc.) and many other things as well. The controller then will modify the model (AJAX, modifying innerHtml, etc.). Changes in the model will automatically be reflected in the view (e.g. if JavaScript changes a node's class).&lt;br /&gt;&lt;br /&gt;The more I think about it, the more I am satisfied that XHTML + CSS + JavaScript is indeed a simple example of MVC.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31053906-115276574461685296?l=ringinginunison.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ringinginunison.blogspot.com/feeds/115276574461685296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31053906&amp;postID=115276574461685296' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115276574461685296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31053906/posts/default/115276574461685296'/><link rel='alternate' type='text/html' href='http://ringinginunison.blogspot.com/2006/07/mvc-as-simple-as-html.html' title='MVC, as simple as HTML?'/><author><name>Brice</name><uri>http://www.blogger.com/profile/01516445020471037382</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
