Archive for July, 2007

Tad Anderson posted about the release of an SOA-related e-book from Microsoft concerning Service Oriented Architecture (SOA). This is one area in which Microsoft has remained notably quiet compared with competing enterprise software vendors such as IBM and Sun. As Tad points out in his post, Microsoft has made some forays into SOA publications and they have been pretty readable.

Their most recent publication, SOA in the Real World (mirrored here), is one of the better pieces of SOA writing that I’ve encountered, vendor-specific or otherwise. It uses Microsoft technologies to illustrate certain principles but it manages to maintain a largely implementation-agnostic viewpoint. The e-book has multiple authors but it was edited together in a very seamless way, which is not always the easiest thing to pull off.

SOA In The Real World

The e-book appears to have been pulled together by Microsoft’s Architectural Resource Center (ARC). No authors are listed specifically and the ARC branding is new, somewhat resembling the branding used for Microsoft’s Architecture Journal. The publication includes a pretty sound enterprise SOA approach, detailed explanations of how some of the major pieces of a SOA come together and a description of how Microsoft’s technologies fit in the mix. Whether one architect’s opinion or the Microsoft party line, there are some insightful and succinct explanations provided, such as the differences between Workflow Foundation and BizTalk when it comes to implementing workflow.

This book is a great read for anyone looking for a solid introduction to SOA and could well be the definitive read for anyone dealing with SOA and Microsoft technologies.

Comments No Comments »

I was performing functional tests on my models that employed Attachment_Fu this morning and thought it would be worthwhile to share the code since it was a bit of a hassle pulling it together. Kudos to Mike Subelsky for his introduction to functional testing Attachment_Fu. It got me going in the right direction. What proved difficult once again was the multi-model controller. Once I got over that hump, I was on my way. As you can see from all the detail in the HTTP POST below, that was not an entirely easy task.

class ProductsControllerTest < Test::Unit::TestCase 
... 
def test_create_with_user     
num_products = Product.count     
imgdata = fixture_file_upload('/files/image.png', 'image/png')     
audiodata = fixture_file_upload('/files/sound.mp3', 'audio/mpeg')     
post :create, {:product => {
:name => "Widget",
:description => "A small tool-like item",
:weight => "3",
:price => "19.99",
:language_id => "1"
},
:image => {:uploaded_data => imgdata},
:audio => {:uploaded_data => audiodata} ,
:html => { :multipart => true }
},
{:user_id => users(:valid_active_user).id}
assert_response :redirect
assert_redirected_to :action => 'show'
assert_equal num_products + 1, Product.count
end
...
end

Comments No Comments »

Continuing my Rails on Windows thread, I’m going to spend a bit of time on something that’s brought me both some substantial gains and some minor woes lately, running the Attachment_Fu plugin on Windows. I’ll start off with some general Attachment_Fu information and then get into some of the quirks, which are, as expected, mostly specific to the Windows environment.

Attachment_Fu On Windows

First, for those not in the know, Attachment_Fu is a Rails plugin that allows you to store binary data (e.g. images, video, documents) and associate it with other models in your Rails application. Metadata (content type, size, height, width) about the attachment is stored in a separate model. Attachment_Fu’s sweet spot is handling images. It can handle automatic image conversion and thumbnailing using a number of popular image processors such as ImageScience, RMagick, or minmagick. Although not provided, you can imagine that Attachment_Fu might be extended to handle other types of binary processing utilities such as PDF converters or audio/video transcoding software. The other very cool thing about Attachment_Fu is that it provides support for pluggable persistence mechanisms. Out of the box, it allows for storage on the file system, as binary information in a database or on Amazon’s S3 storage service.

There is an abundance of information already written about Attachment_Fu so to avoid re-inventing the wheel, I’ll provide what I found to be the best sources of information to start.

  • Mike Clark’s tutorial is the gold standard introduction to using Attachment_Fu. The code is simplistic but rock solid. It covers using both the file system and S3 for storage and will get you up and running on Attachment_Fu in no time.
  • Some posts on the Attachment_Fu message board provide a solution to associating the attachment model with another model (i.e. making it an attachment to something). The posts provide both the controller and the view code for uploading the initial attachment and rendering it. Handling the attachment relationship in your MVC is going to be a fairly common requirement and most Attachment_Fu users will benefit from these posts.

For my part, I’m going to provide some controller source code for updating the attachment when you have a relationship with another model (an extension of the second item above) since this is one area that wasn’t covered well anywhere else and might save you some time in your travels. In the code below, my main model is the product and the image is the model where a photo and thumbnail are stored using Attachment_Fu.

class ProductController < ApplicationController

def update     @product = Product.find(params[:id])
# Load up product categories for the view
@all_categories = Category.find(:all, ::order=>"name_en")
if @product.update_attributes(params[:product])
if !params[:image][:uploaded_data].blank?
# My product only has one image / thumbnail, I'll destroy 'each'
# wait 3 # See quirk no.1 below
@product.images.each {|img| img.destroy}
@image = @product.images ||= Image.new
@image = @product.images.build(params[:image])
@image.save
end
flash[:notice] = 'Product was successfully updated.'
redirect_to :action => 'show', :id => @product
else
render :action => 'edit'
end
end

end

The links above, in combination with my snippet, should get you through creating an attachment and handling CRUD for an attachment and its parent model from a single view. Now comes the Windows quirkiness. Not knowing to expect these Attachment_Fu quirks and then having to root out the cause of the behavior took up a lot of time. It turns out that most of I found that most of the quirks are documented in some way, shape, or form. I’ve pulled together a list of the quirks as well as some best practice workarounds.

  • When running Attachment_Fu on Windows, the most commonly accounted problem is the “Size Is Not Included In List” validation error. It appears that no amount of fixing in the Ruby code is going to help here since it appears to be a Windows file system issue. The workaround is really simple, just add a wait x statement before your attachment processing and things will be golden. The x (which denotes seconds) time will vary based upon the size of the attachments you are processing. Bigger attachments require more of a wait. Also, be sure to comment this code out in production since this is a Windows only issue.

7/19/2007 Update – Rick suggested using RUBY_PLATFORM to determine if the wait should be invoked. I tested this and it worked as suggested

  • When you invoke the destroy method on your attachment using Attachment_Fu on Windows, your models reference to the attachment will be deleted but the physical attachments themselves will not be deleted if you have persisted them to the file system. If you look at the Attachment_Fu source code or your log files, you’ll see that Attachment_Fu assumes that you are using a UNIX-based system and executes UNIX commands like rm to remove these files. These commands will obviously not work in a Windows environment, leaving you with a bunch of zombie files. This should not be a problem if you use a database or S3 persistence mechanism since these mechanisms are independent of the operating system.

7/19/2007 Update – Rick corrected me. He is indeed calling the OS safe FileUtils.rm in the file system backend. It still isn’t working though – at least on my machine.

  • My last Windows specific quirk is actually an Internet Explorer issue. If your attachments are images, you may have problems with uploading JPEG’s using the default Attachment_Fu plugin. From what I’ve been able to determine, if you upload a JPEG from IE with a file extension of .JPEG, IE will set the MIME type to image/pjpeg for a progressive JPEG. However, if the image extension is simply .jpg, IE will set the MIME type to image/jpg. This MIME type, however, is not included in the default list of content types accepted by Attachment_Fu. My suggestion is to add this type to the list in the source code until Rick can get around to modifying the source.

7/19/2007 Update – The MIME type was added to source. For reference, Rick suggested that this could have been done without changing the source simply by adding
Technoweenie::AttachmentFu.content_types << ‘image/jpg

The last quirk for my post should be meaningful to all of those using Capistrano, the Rails migration utility. Capistrano manages versions of the application for rollforward / rollback by creating symlinks to previous versions of an application and deploying the most recent version of your entire application tree from your version control system (e.g. Subversion). However, since it’s very unlikely that you are storing all of the attachments for your application under version control, the attachments will be unlinked and no longer available when you migrate a new version of your application to production. To get around this issue, the solution proposed here creates a separate physical directory for the attachments outside of your application’s directory and then updates a symlink from your application’s attachment directory to the separate physical directory every time you migrate.

Comments 1 Comment »

I’ve had some really good experiences with some of the iTunes Original collections, which include a mix of pre-existing songs, original versions of hits and artist narrations. I’ve especially enjoyed the iTunes Originals with Rob Thomas. This weekend, I picked up my first iTunes Exclusive Live Sessions mix. The Live Sessions series at 5 or 6 songs per collection offers only about half the music of your average Original collection but, as the title indicates, it’s all live music.

Since I’ve downloaded the Five for Fighting Live Session from iTunes, I have not been able to get the music off of my mind. I’ve been listening to Five for Fighting since their first CD, which accompanied my wife and I on a memorable trip down the US West Coast. Even if you can’t associate the Five for Fighting name with a particular song, it’s fairly likely that you’ve heard their music since it gets a good amount of radio play and has found favor with a number of TV commercial producers.

iTunes Exclusive - Five for Fighting

Granted, you are not going to get any original music here but what you do get is Five for Fighting’s best material done live in a pure acoustic (piano and guitar) format. The album is tight and the recording quality is superb. Artist narration, storytelling, and interludes are edited out except for one story about the writing of the song Two Lights which really accentuates that piece. At about $5 for the collection, you really can’t go wrong with this one whether you are an old fan or someone simply looking to pick up some great music to listen to.

Comments No Comments »

I’ve been putting a good deal of time recently into converting GeoGlue from .NET to Rails. One of the things that I’m looking to get into the alpha release is the dynamic creation of podcasts. This is really nothing special since a podcast is little more than a special case of an RSS feed that points at external media files (i.e. audio or video).

Podcast Creation From Rails

I plan on covering the audio/video entry in an upcoming post about the nuances of the Attachment_Fu plugin on Windows. In this post, I’m going to just lay out the code for the podcast creation, since this is nothing more that a simple rxml file. I’ve sprinkled in comments liberally but most of the code should be fairly self explanatory to those familiar with Ruby and RSS feeds.

xml.instruct! ::xml, :version=&gt;&quot;1.0&quot;, :encoding=&gt;&quot;UTF-8&quot;
xml.rss('version' =&gt; '2.0') do
xml.channel do
xml.title @podcast.name
# Self-referencing link
xml.link url_for(:only_path =&gt; false)
# Important --&gt; RFC-822 compliant datetime
xml.pubDate(Time.now.strftime(&quot;%a, %d %b %Y %H:%M:%S %Z&quot;))
xml.language &quot;en-us&quot;
xml.ttl &quot;40&quot;
# User who caused the feed to be generated
xml.generator User.find(:first, session[:user_id]).name
xml.description @podcast.description
# 'public_filename' is a method from the Attachment_Fu plugin
xml.image do
xml.url url_for(:controller =&gt; @podcast.images[0].public_filename, ::only_path =&gt; false)
xml.link url_for(:only_path =&gt; false)
xml.title @podcast.name
xml.width @podcast.images[0].width
xml.height @podcast.images[0].height
end
@podcast.entries.each do |entry|
xml.item do
xml.title(entry.title)
xml.link(url_for(:controller =&gt; entry.audios[0].public_filename, ::only_path =&gt; false))
# User who actually generated the media (i.e. audio)
xml.author(entry.user.name)
xml.category &quot;Uncategorized&quot;
xml.guid(url_for(:controller =&gt; entry.audios[0].public_filename, ::only_path =&gt; false))
xml.description(entry.description)
# Simplification, you should pull from updated_at/updated_on
xml.pubDate(Time.now.strftime(&quot;%a, %d %b %Y %H:%M:%S %Z&quot;))
# The enclosure is very important!!
# If you use Attachment_Fu, everything you need is included in the model
xml.enclosure(:type=&gt;entry.audios[0].content_type,
:length=&gt;entry.audios[0].size.to_s,
:url=&gt;url_for(:controller =&gt; entry.audios[0].public_filename, ::only_path =&gt; false)
)
end
end
end
end

A couple of lessons learned from my experience. Firstly, Apple provides some good resources on generating podcasts. This is especially important since the iTunes crowd is a large and important contingent of the feed consuming world. There are iTunes-specific tags (and a schema) available. These tags are not mandatory (I didn’t use them here) but they will help you produce a richer feed for consumption within iTunes. Secondly, since the RXML file is just another view, make sure to turn off any default layouts that you might have applied to your other views. I’ve included a snippet below to demonstrate how to do this. Check your version of Rails, mileage may vary with exempt_from_layout based upon your release.

class ApplicationController &lt; ActionController::Base   

# Pick a unique cookie name to distinguish our session data from others 
session :session_key =&gt; '_trunk_session_id'
layout 'default'
exempt_from_layout :rxml
...

end

My final caveat is not to apply forms-based authentication to your podcast (RXML view). Either make the view public or, if you wish to protect it, do so using HTTP Basic authentication instead. If you’re using both forms-based and HTTP Basic authentication, you’ll probably need to sync the two by using a single LDAP repository. That’s fodder for a completely different post.

Comments No Comments »