<?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-2759245772859176868</id><updated>2011-11-07T00:54:46.042-08:00</updated><category term='iPhone Application'/><category term='jQTouch'/><title type='text'>Ben Ellingson</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>17</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-1046170394388498672</id><published>2011-02-20T09:07:00.000-08:00</published><updated>2011-02-20T09:34:36.612-08:00</updated><title type='text'>Stay Productive with Growl Notifications</title><content type='html'>Being a productive programmer... you would never browse Twitter, Facebook, Digg, or Hacker News while working.  You are focused and on task!  &lt;br /&gt;&lt;br /&gt;Unless, perhaps your full app build or other common task require a few minutes or more of processing?  In order to not waste precious time, I often develop with 2 machines... Or.. I will waste precious time and catch up on my tweets.  One link leads to another, next thing you know... there goes ten or fifteen minutes while waiting on a 2-3 minute build.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Solution: Add a Growl Notification to Your Build&lt;/h3&gt;&lt;br /&gt;Growl notifications are a non-intrusive way to let you know your build is complete.  Setting this up for a Mac is really easy.  I just copy the sample AppleScript, change the notification text, and modify my build to execute the script.  I don't need to make this work on Windows, but I imagine that would be pretty easy to do via another method.&lt;br /&gt;&lt;br /&gt;Growl was already installed on my system, but you may need to install it yourself.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Apple Script Copied from Growl.info&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://growl.info/documentation/applescript-support.php"&gt;http://growl.info/documentation/applescript-support.php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;tell application "GrowlHelperApp"&lt;br /&gt; -- Make a list of all the notification types&lt;br /&gt; -- that this script will ever send:&lt;br /&gt; set the allNotificationsList to ¬&lt;br /&gt;  {"Test Notification" , "Another Test Notification"}&lt;br /&gt;&lt;br /&gt; -- Make a list of the notifications&lt;br /&gt; -- that will be enabled by default.&lt;br /&gt; -- Those not enabled by default can be enabled later&lt;br /&gt; -- in the 'Applications' tab of the growl prefpane.&lt;br /&gt; set the enabledNotificationsList to ¬&lt;br /&gt;  {"Test Notification"}&lt;br /&gt;&lt;br /&gt; -- Register our script with growl.&lt;br /&gt; -- You can optionally (as here) set a default icon&lt;br /&gt; -- for this script's notifications.&lt;br /&gt; register as application "Growl AppleScript Sample" ¬&lt;br /&gt;   all notifications allNotificationsList ¬&lt;br /&gt;   default notifications enabledNotificationsList ¬&lt;br /&gt;   icon of application "Script Editor"&lt;br /&gt;&lt;br /&gt; -- Send a Notification...&lt;br /&gt; notify with name "Test Notification" ¬&lt;br /&gt;   title "Build Complete" ¬&lt;br /&gt;   description "NFJS Build Complete" ¬&lt;br /&gt;   application name "Growl AppleScript Sample"&lt;br /&gt;&lt;br /&gt; notify with name "Another Test Notification" ¬&lt;br /&gt;   title "Another Test Notification :) " ¬&lt;br /&gt;   description "Alas — you won't see me until you enable me..." ¬&lt;br /&gt;   application name "Growl AppleScript Sample"&lt;br /&gt;&lt;br /&gt;end tell&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Execute the Script from Your Build&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;I'm using a gant based build, so executing the script is pretty simple. &lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;"osascript bin/build_notify.scpt".execute()&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Congrats, now you'll be privy to fewer breaking stories about the next iPhone and such; but you will get more done!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-1046170394388498672?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/1046170394388498672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2011/02/stay-productive-with-growl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/1046170394388498672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/1046170394388498672'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2011/02/stay-productive-with-growl.html' title='Stay Productive with Growl Notifications'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-2531674021997291569</id><published>2011-01-28T10:30:00.000-08:00</published><updated>2011-01-28T11:07:48.197-08:00</updated><title type='text'>Objective-C Core Data EntityManager</title><content type='html'>If you plan to create an iPhone, iPad, or Cocoa application that requires data storage, you are going to need to use the Core Data framework.  Core Data is a great framework.  It saves you the pain of writing redundant data access code.. SQL, etc.  Also, I really like the graphical tool used to create entity models.&lt;br /&gt;&lt;br /&gt;However, I find the Core Data API to be overly complicated and exceedingly verbose.  When compared to other modern ORM APIs, it takes a lot of work to do simple entity management tasks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example: Fetch a Collection of Books using Core Data&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;- (void) testCoreDataQuery {&lt;br /&gt; &lt;br /&gt; NSManagedObjectContext *managedObjectContext = [self managedObjectContext];&lt;br /&gt; &lt;br /&gt; &lt;br /&gt; NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];&lt;br /&gt; &lt;br /&gt; fetchRequest.entity = [NSEntityDescription entityForName: @"Book" &lt;br /&gt;    inManagedObjectContext: managedObjectContext];&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] &lt;br /&gt;           initWithKey: @"title"  ascending: YES] autorelease];&lt;br /&gt; [fetchRequest setSortDescriptors: [NSArray arrayWithObject: sortDescriptor]];&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt; NSFetchedResultsController *fetchResultsController = &lt;br /&gt;  [[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest &lt;br /&gt;          managedObjectContext:managedObjectContext&lt;br /&gt;         sectionNameKeyPath:nil&lt;br /&gt;            cacheName:nil] autorelease];&lt;br /&gt; &lt;br /&gt; &lt;br /&gt; NSError *error = nil;&lt;br /&gt; if(![fetchResultsController performFetch:&amp;error]) {&lt;br /&gt;  NSLog(@"FETCH ERROR: %@",[error userInfo]);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; NSArray *entities = [fetchResultsController fetchedObjects];&lt;br /&gt; &lt;br /&gt; NSLog(@"found %d books",entities.count);&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That is a lot of code to write to perform what should be a really simple operation.  This example doesn't even include any sort or selection criteria.  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Introducing BEEntityManager&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To simplify interaction with Core Data, I created a simple Entity Manager API which is inspired by the Java Persistence API.  I'm guessing there are other APIs like this available, but I haven't bothered to look.  Let me know if you know of any.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example: Fetch a Collection Using BEEntityManager&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;- (void) testBEEntityManagerQuery {&lt;br /&gt; &lt;br /&gt; BEEntityManager *entityManager = [[[BEEntityManager alloc] init] autorelease];&lt;br /&gt; &lt;br /&gt; NSArray *books = [entityManager query: @"Book" criteria: @"author = 'F. Scott Fitzgerald'" sort: @"title" ascending: YES ];&lt;br /&gt; &lt;br /&gt; NSLog(@"found %d books",books.count);&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is a much easier and more maintainable way to interact with a data store.  To each their own though.. it's not for everyone... some people like pain.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;BEEntityManager API Features&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The entity manager includes simple methods for your common data store operations.&lt;br /&gt;&lt;br /&gt;query&lt;br /&gt;get&lt;br /&gt;create&lt;br /&gt;createOrUpdate&lt;br /&gt;save&lt;br /&gt;delete&lt;br /&gt;&lt;br /&gt;It also simplifies accessing and managing instances of NSManagedObjectContext.  This is helpful in apps of any significant size.&lt;br /&gt;&lt;br /&gt;You can download &lt;a href="https://github.com/benellingson/BEEntityManager"&gt;BEEntityManager from github&lt;/a&gt;.   To see examples of how to use the API, take a look at the BEEntityManagerTest class.  If you find it useful, please let me know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-2531674021997291569?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/2531674021997291569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2011/01/objective-c-core-data-entitymanager.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2531674021997291569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2531674021997291569'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2011/01/objective-c-core-data-entitymanager.html' title='Objective-C Core Data EntityManager'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-3145534936189448477</id><published>2010-12-01T08:50:00.000-08:00</published><updated>2010-12-01T08:54:01.601-08:00</updated><title type='text'>Rich Web Experience iOS Workshop</title><content type='html'>Yesterday, I enjoyed hosting another iOS Workshop with &lt;a href="http://www.therichwebexperience.com/conference/fort_lauderdale/2010/11/speakers/matthew_mccullough"&gt;Matthew McCullough&lt;/a&gt;. This was at the &lt;a href="http://www.therichwebexperience.com/conference/fort_lauderdale/2010/11/ipad_workshop"&gt;Rich Web Experience&lt;/a&gt;.  With about 70 developers in attendance, we had a great turn out again.  &lt;br /&gt;&lt;br /&gt;This workshop was an all day session.  Our attendees were experienced Java developers, so we started with a lecture on Objective-C.  This was a hands-on coding workshop, so we had everyone writing code throughout the day.  &lt;br /&gt;&lt;br /&gt;In the morning, our focus was on the fundamentals of Objective-C syntax and getting comfortable with XCode.  In the afternoon, we jumped into using Interface Builder and created an iPad application.  This application covered the use of application templates, with a focus on a tab based controller app.  &lt;br /&gt;&lt;br /&gt;The next steps included: adding a Map to a view, creating a view with a table and label, exploring other ui components, creating an enhanced table view, and finally we used a UIPopoverController and a UIWebView to present a content detail view.&lt;br /&gt;&lt;br /&gt;That is the short story, we covered a lot of iOS fundamentals in a single day.  The workshop went really smoothly thanks to the help we received from: &lt;a href="http://www.therichwebexperience.com/conference/fort_lauderdale/2010/11/speakers/tim_berglund"&gt;Tim Berglund&lt;/a&gt;, &lt;a href="http://www.therichwebexperience.com/conference/fort_lauderdale/2010/11/speakers/pratik_patel"&gt;Pratik Patel&lt;/a&gt;, and Johnny Wey.  During the workshop, they roamed the room and helped out those who were stuck.  This allowed Matthew and I to focus on the larger group.  This was a great help!  So far, the feedback has been very positive.  Hope to do it again in 2011!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-Qe3IbRFsL4/TPZ9QMNgvQI/AAAAAAAAA74/Nk9npG4o0IE/s1600/RWX_iOS_Workshop.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 299px;" src="http://1.bp.blogspot.com/_-Qe3IbRFsL4/TPZ9QMNgvQI/AAAAAAAAA74/Nk9npG4o0IE/s400/RWX_iOS_Workshop.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5545757708262620418" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-3145534936189448477?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/3145534936189448477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/12/rich-web-experience-ios-workshop.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/3145534936189448477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/3145534936189448477'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/12/rich-web-experience-ios-workshop.html' title='Rich Web Experience iOS Workshop'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-Qe3IbRFsL4/TPZ9QMNgvQI/AAAAAAAAA74/Nk9npG4o0IE/s72-c/RWX_iOS_Workshop.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-5418400139956176441</id><published>2010-10-23T11:34:00.000-07:00</published><updated>2010-10-23T12:04:16.138-07:00</updated><title type='text'>Identifying Untested Code with Cobertura</title><content type='html'>With the No Fluff Just Stuff code base, I'm currently at 87% code coverage.  Life at this level of coverage is pretty good.  I'm rarely surprised by bugs as a result of untested code.  Most untested code is pretty inconsequential stuff; such as, legacy (pre-groovy era code) that was originally written only to handle checked exceptions.&lt;br /&gt;&lt;br /&gt;That said.. I'm always trying to increase coverage.   My code base is just shy of 20,000 lines of code.  To increase coverage by %1,  I have to add 200 lines of coverage.  Uncovered lines are sprinkled throughout the codebase and rarely in blocks larger than 1-3 lines. Writing a unit test to cover 1-3 lines typically involves writing 5-10+ lines of unit test code. So at this point, a %1 increase in test coverage is a lot of work and is something to celebrate.&lt;br /&gt;&lt;br /&gt;The html reports generated by cobertura are great, but I find that they don't point me directly to the class with the most untested lines of code.  So using the xml report, I wrote a simple gant (groovy) target to generate a report which orders classes by lines of uncovered code.&lt;br /&gt;&lt;br /&gt;It is a simple script that took me about 30 minutes to write, but should help me attack my uncovered code a little more efficiently.&lt;br /&gt;&lt;br /&gt;This script is on github: &lt;a href="http://gist.github.com/642533"&gt;http://gist.github.com/642533&lt;/a&gt;.  clone url: git://gist.github.com/642533.git&lt;br /&gt;&lt;br /&gt;Sample output:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-Qe3IbRFsL4/TMMvhqcmazI/AAAAAAAAA7w/QI9bdivCUqs/s1600/Screen+shot+2010-10-23+at+1.51.39+PM.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 233px;" src="http://2.bp.blogspot.com/_-Qe3IbRFsL4/TMMvhqcmazI/AAAAAAAAA7w/QI9bdivCUqs/s320/Screen+shot+2010-10-23+at+1.51.39+PM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5531317022717537074" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-5418400139956176441?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/5418400139956176441/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/10/identifying-untested-code-with.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/5418400139956176441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/5418400139956176441'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/10/identifying-untested-code-with.html' title='Identifying Untested Code with Cobertura'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_-Qe3IbRFsL4/TMMvhqcmazI/AAAAAAAAA7w/QI9bdivCUqs/s72-c/Screen+shot+2010-10-23+at+1.51.39+PM.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-2850047169724391498</id><published>2010-08-19T09:16:00.000-07:00</published><updated>2010-08-19T09:16:00.246-07:00</updated><title type='text'>Summer in Michigan and Seattle + Orca Video</title><content type='html'>Wow, it really has been a great summer.  I spent most of it in my home town, Marquette in Michigan's Upper Peninsula.  Marquette is a great little city on Lake Superior.  The weather is fair, beaches are beautiful, and it has world class mountain biking trails that are easily accessed from anywhere in town.  &lt;br /&gt;&lt;br /&gt;I bought a Jeep Wrangler and did a lot of camping and exploring in the deep woods of the UP.  You can checkout the photos on &lt;a href="http://www.flickr.com/photos/benellingson/"&gt;flickr&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I also spent 3 weeks in Seattle with my girlfriend Amy.  She participated in a teaching program there, so I tagged along... telecommuting is a great thing :)   On the weekends, we made 2 trips to Olympic National Park and one trip to San Juan Island.  &lt;br /&gt;&lt;br /&gt;On San Juan Island, we went sea kayaking with &lt;a href="http://www.sea-quest-kayak.com/"&gt;Sea Quest Expeditions&lt;/a&gt;.  The guides from Sea Quest are great and we were really lucky to come across several pods of Orca whales.  Check out my little video..&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/hP7_WrlWgV8?fs=1&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/hP7_WrlWgV8?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-2850047169724391498?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/2850047169724391498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/08/summer-in-michigan-and-seattle-orca.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2850047169724391498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2850047169724391498'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/08/summer-in-michigan-and-seattle-orca.html' title='Summer in Michigan and Seattle + Orca Video'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-6867357795611794201</id><published>2010-08-18T08:48:00.000-07:00</published><updated>2010-08-18T09:15:44.888-07:00</updated><title type='text'>Objective-C Refcard @ DZone.com</title><content type='html'>&lt;a href="http://refcardz.dzone.com/refcardz/objective-c-iphone-and-ipad"&gt;&lt;br /&gt;&lt;img src="http://refcardz.dzone.com/sites/all/files/refcardz/thumbs/26935.png" style="float: left;margin: 0 10px 10px 0;" alt="Objective-C for the iPhone and iPad" /&gt;&lt;/a&gt;My first DZone Refcard &lt;a href="http://refcardz.dzone.com/refcardz/objective-c-iphone-and-ipad"&gt;Objective-C for the iPhone and iPad&lt;/a&gt; is now available.  I collaborated with &lt;a href="http://ambientideas.com/blog/"&gt;Matthew McCullough&lt;/a&gt; on this project.&lt;br /&gt;&lt;br /&gt;In 5.5 pages, this refcard describes and has code examples of the Objective-C language and tools.   There are a few additional topics that I would like to have covered, but I believe we hit the key points.  I would love to hear your feedback; please leave comments here or send me an email: benellingson .at. yahoo.&lt;br /&gt;&lt;br /&gt;The folks at DZone and our several reviewers were a big help!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-6867357795611794201?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/6867357795611794201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/08/objective-c-refcard-dzonecom.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/6867357795611794201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/6867357795611794201'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/08/objective-c-refcard-dzonecom.html' title='Objective-C Refcard @ DZone.com'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-3029262081986373222</id><published>2010-06-17T13:22:00.001-07:00</published><updated>2010-06-17T14:03:05.727-07:00</updated><title type='text'>Über Conf iPad Workshop</title><content type='html'>&lt;a href="http://ambientideas.com/blog/"&gt;Matthew McCullough&lt;/a&gt; and I had a great time hosting the &lt;a href="http://uberconf.com/conference/denver/2010/06/ipad_seminar"&gt;Über Conf iPad Workshop&lt;/a&gt;!  90+ developers attended the main 4 hour workshop on Monday.  The Tuesday and Wednesday night sessions were also well attended.  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_-Qe3IbRFsL4/TBqK39RJ3OI/AAAAAAAAA7E/tToDsq6_70k/s1600/UberConf_IMG_7194.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width:500px;" src="http://1.bp.blogspot.com/_-Qe3IbRFsL4/TBqK39RJ3OI/AAAAAAAAA7E/tToDsq6_70k/s320/UberConf_IMG_7194.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5483848190220950754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Monday's workshop included: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;overview of the iPhone OS development landscape&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Objective-C language lecture and comparison to Java&lt;/li&gt;&lt;br /&gt;&lt;li&gt;hands-on coding of simple Objective-C command line apps&lt;/li&gt;&lt;br /&gt;&lt;li&gt;tour of Interface Builder&lt;/li&gt;&lt;br /&gt;&lt;li&gt;connecting controls and event handlers to controller classes&lt;/li&gt;&lt;br /&gt;&lt;li&gt;hands-on coding of a simple iPad app&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I spent the majority of the Tuesday night 90-minute session live coding.  Live coding can be a challenge, especially if you don't do it often.  Fortunately, the session went smoothly.  I had a lot of fun with it.&lt;br /&gt;&lt;br /&gt;In this hands-on coding session we walked through the creation of a web service application that deserialized JSON data and displayed the content in a UITableView. This application used Über Conf conference speaker data.&lt;br /&gt;&lt;br /&gt;Steps followed:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;created a iPad app using a blank window app  template&lt;/li&gt;&lt;br /&gt;&lt;li&gt;added a UIViewController to the app delegate, MainWindow.xib and connected the two&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Created a SpeakerListController class and .xib file&lt;/li&gt;&lt;br /&gt;&lt;li&gt;explored the mechanisms of UITableViewController to populate a TableView with some simple static data&lt;/li&gt;.&lt;br /&gt;&lt;li&gt;copied the TouchJSON api into our project&lt;/li&gt;&lt;br /&gt;&lt;li&gt;deserialized speaker records from JSON into an NSArray rowData&lt;/li&gt;&lt;br /&gt;&lt;li&gt;populated the UITableView with the speaker names&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Using UITableViews is a key iPad / iPhone skill, so I am pleased that we were able to help attendees code along through these steps.&lt;br /&gt;&lt;br /&gt;We continued the session for another 90-minutes on Wednesday night.  We picked up again coding on the web service application.  We walked through the steps to create a speaker detail view and display the view using a UIPopoverController.  UIPopoverController is an iPad specific control for displaying content within a smaller popover view.&lt;br /&gt;&lt;br /&gt;Then we went on to demo the &lt;a href="http://itunes.apple.com/us/app/uber-conf/id369913607?mt=8"&gt;Über Conf conference&lt;/a&gt; application.  During this demo, we discussed the Core Data framework and demoed the process for generating our domain entity classes.  &lt;br /&gt;&lt;br /&gt;Finally, we finished up the session by walking through the process to create and install a developer provisioning profile; and to deploy the application to a participants iPad.&lt;br /&gt;&lt;br /&gt;We had a great time with this workshop.  We hope to host it again at the Rich Web Experience in December.  &lt;br /&gt;&lt;br /&gt;It was great to have an opportunity to work with Matthew McCullough.  I learned a lot!  Also, thanks to &lt;a href="http://twitter.com/tlberglund"&gt;Tim Berglund&lt;/a&gt; and &lt;a href="http://twitter.com/fredjean"&gt;Fred Jean&lt;/a&gt; for helping throughout the workshop. And thanks to all those who came!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-3029262081986373222?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/3029262081986373222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/06/uber-conf-ipad-workshop.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/3029262081986373222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/3029262081986373222'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/06/uber-conf-ipad-workshop.html' title='Über Conf iPad Workshop'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-Qe3IbRFsL4/TBqK39RJ3OI/AAAAAAAAA7E/tToDsq6_70k/s72-c/UberConf_IMG_7194.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-2392571492763169891</id><published>2010-05-07T06:21:00.000-07:00</published><updated>2010-05-07T06:49:36.612-07:00</updated><title type='text'>Über Conf iPad App</title><content type='html'>I've had my iPad for three weeks now and my first iPad app is &lt;a href="http://itunes.apple.com/us/app/uber-conf/id369913607?mt=8"&gt;now available on the App store&lt;/a&gt;.  This app is for the &lt;a href="http://uberconf.com"&gt;Über Conf&lt;/a&gt; conference coming up June 14-17.  If you are interested in Über Conf, this app will help you browse sessions and plan your itinerary. &lt;br /&gt;&lt;br /&gt;Even more exciting for me is that, Matthew McCullough and I will be teaching an &lt;a href="http://uberconf.com/conference/denver/2010/06/ipad_seminar"&gt;iPad/iPhone workshop at Über Conf&lt;/a&gt;.  Registration for the workshop includes an iPad!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;&lt;a style="color: #CC0000;" href="http://itunes.apple.com/us/app/uber-conf/id369913607?mt=8"&gt;Get the Über Conf iPad App&lt;/a&gt;&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;I'm not going to provide a full iPad review. There are plenty of reviews floating around.. but I will say that  I really like mine.  This device is really handy and there are a lot of cool apps coming out.  If you get one, be sure to get the case.  It is awkward to use without. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-Qe3IbRFsL4/S-QYd_0tOsI/AAAAAAAAA6c/bXi1lVLL1W4/s1600/uber_ipad.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 240px; height: 320px;float: left;margin: 10px 20px 20px 0;" src="http://3.bp.blogspot.com/_-Qe3IbRFsL4/S-QYd_0tOsI/AAAAAAAAA6c/bXi1lVLL1W4/s320/uber_ipad.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5468522751162399426" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-Qe3IbRFsL4/S-QZ4eaEx2I/AAAAAAAAA6k/KwiIxAW_POE/s1600/ipad_medium.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 233px; height: 320px;float: left;margin: 10px 20px 20px 0;" src="http://4.bp.blogspot.com/_-Qe3IbRFsL4/S-QZ4eaEx2I/AAAAAAAAA6k/KwiIxAW_POE/s320/ipad_medium.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5468524305560422242" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-2392571492763169891?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/2392571492763169891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/05/uber-conf-ipad-app.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2392571492763169891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2392571492763169891'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/05/uber-conf-ipad-app.html' title='Über Conf iPad App'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-Qe3IbRFsL4/S-QYd_0tOsI/AAAAAAAAA6c/bXi1lVLL1W4/s72-c/uber_ipad.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-7837446060518377231</id><published>2010-04-13T21:49:00.001-07:00</published><updated>2010-06-08T07:04:35.876-07:00</updated><title type='text'>The Missing Universal iPad/iPhone App Template</title><content type='html'>The ideal way to package your app for the iPhone and iPad is to create a single "Universal" App.  This style of app allows you to customize your interface for each device while reusing common code.  In addition, a single Universal app is best, so you don't confuse users with the requirement to download multiple versions of your app.  &lt;br /&gt;&lt;br /&gt;&lt;b&gt;XCode 3.2 does not include an ideal template for creating a Navigation-based Universal App&lt;/b&gt;.  Apple has said that iPad apps should respect all device orientations.  Meaning if you turn the device, the app should redisplay in the new orientation.  &lt;br /&gt;&lt;br /&gt;Getting the Navigation Bar and Orientation working correctly can be a little tricky to accomplish if you don't start out with a good template.  It's fairly simple once you understand the required elements, but that can be a painful process.  I created this template to save time.  The template is also configured for Core Data.  If demand exists, I will create a version without Core Data.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://github.com/benellingson/Universal-Navigation-based-Application"&gt;The template is hosted at github&lt;/a&gt;.  The following commands will install the template in your local XCode templates folder.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;mkdir -p "$HOME/Library/Application Support/Developer/Shared/XCode/Project Templates/My Templates"&lt;br /&gt;&lt;br /&gt;cd "$HOME/Library/Application Support/Developer/Shared/XCode/Project Templates/My Templates"&lt;br /&gt;&lt;br /&gt;git clone git://github.com/benellingson/Universal-Navigation-based-Application.git&lt;br /&gt;&lt;br /&gt;rm -rf "Universal-Navigation-based-Application/.git"&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Once the template is installed it will appear under "My Templates" when you create a New Project.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-Qe3IbRFsL4/S8VTjh3il9I/AAAAAAAAA6U/mmIl8jVdxiA/s1600/Universal-Navigation-based-Template.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_-Qe3IbRFsL4/S8VTjh3il9I/AAAAAAAAA6U/mmIl8jVdxiA/s320/Universal-Navigation-based-Template.jpg" border="0" alt="Universal Navigation-based Application" id="BLOGGER_PHOTO_ID_5459861993108445138" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you find this helpful or have suggestions, please leave a comment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-7837446060518377231?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/7837446060518377231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/04/missing-ipad-app-template.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/7837446060518377231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/7837446060518377231'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/04/missing-ipad-app-template.html' title='The Missing Universal iPad/iPhone App Template'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_-Qe3IbRFsL4/S8VTjh3il9I/AAAAAAAAA6U/mmIl8jVdxiA/s72-c/Universal-Navigation-based-Template.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-6294352656574042669</id><published>2010-03-14T16:50:00.000-07:00</published><updated>2010-03-14T16:58:18.822-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jQTouch'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone Application'/><title type='text'>No Fluff Just Stuff iPhone App</title><content type='html'>&lt;a href="http://itunes.apple.com/us/app/nfjs/id359059288?mt=8" target="new"&gt;&lt;br /&gt;&lt;img style="margin: 0pt 20px 20px 0pt; float: left;border: 0;" src="http://3.bp.blogspot.com/_-Qe3IbRFsL4/S51ru8N8yvI/AAAAAAAAA50/JPoiK0Srkao/s320/nfjs_iphone_app_175x175.jpg" alt="" id="BLOGGER_PHOTO_ID_5448629578370960114" border="0" /&gt;&lt;/a&gt;I'm pleased to announce availability of the &lt;a href="http://www.nofluffjuststuff.com/"&gt;NFJS&lt;/a&gt; iPhone App in the &lt;a href="http://itunes.apple.com/us/app/nfjs/id359059288?mt=8" target="new"&gt;App Store&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Use the NFJS app when attending No Fluff Just Stuff conferences (&lt;a href="http://www.nofluffjuststuff.com"&gt;nofluffjuststuff.com&lt;/a&gt;). The app allows you to browse the conference schedule, speaker information, and presentation abstracts. This app helps you plan your conference itinerary.&lt;br /&gt;&lt;br /&gt;This is my second iPhone App.  The application is a simple webapp hosted at &lt;a href="http://www.nofluffjuststuff.com/"&gt;nofluffjuststuff.com&lt;/a&gt;.  I created it using &lt;a href="http://www.jqtouch.com/"&gt;jQTouch&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;When you need to create a simple data driven iPhone app, jQTouch is a great framework to use.  jQTouch allows you to create webapps that have a native iPhone look-and-feel, animations, and behavior.  I'm able to develop an app like this much faster than a native iPhone SDK App.  Also, once the application is in the App Store, it is not necessary to publish updates through the App Store submission process.  All you have to do is deploy a new version of the web app.  This is huge because the app store process usually takes at least 2 weeks. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://itunes.apple.com/us/app/nfjs/id359059288?mt=8" target="new" style="color: #CC0000;text-decoration: underline;"&gt;&lt;h3 style="text-align: center;"&gt;Get the NFJS iPhone App&lt;/h3&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-Qe3IbRFsL4/S51sNLQKGSI/AAAAAAAAA58/4o7ZW2RZNo0/s1600-h/screenshot1.jpg"&gt;&lt;br /&gt;&lt;img style="cursor: pointer; width: 222px; height: 320px; margin: 0pt 0 0 60px;" src="http://2.bp.blogspot.com/_-Qe3IbRFsL4/S51sNLQKGSI/AAAAAAAAA58/4o7ZW2RZNo0/s320/screenshot1.jpg" alt="" id="BLOGGER_PHOTO_ID_5448630097802828066" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-Qe3IbRFsL4/S51sRrayZ3I/AAAAAAAAA6E/ccjQeQYP-ZI/s1600-h/screenshot2.jpg"&gt;&lt;img style="cursor: pointer; width: 222px; height: 320px; margin: 0pt 0 0 60px;" src="http://4.bp.blogspot.com/_-Qe3IbRFsL4/S51sRrayZ3I/AAAAAAAAA6E/ccjQeQYP-ZI/s320/screenshot2.jpg" alt="" id="BLOGGER_PHOTO_ID_5448630175156823922" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {} href="http://4.bp.blogspot.com/_-Qe3IbRFsL4/S51sWLuYldI/AAAAAAAAA6M/4Kt7-Yk4vrk/s1600-h/screenshot3.jpg"&gt;&lt;img style="cursor: pointer; width: 222px; height: 320px;margin: 0pt 0 0 60px;" src="http://4.bp.blogspot.com/_-Qe3IbRFsL4/S51sWLuYldI/AAAAAAAAA6M/4Kt7-Yk4vrk/s320/screenshot3.jpg" alt="" id="BLOGGER_PHOTO_ID_5448630252548429266" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-6294352656574042669?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/6294352656574042669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/03/no-fluff-just-stuff-iphone-app.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/6294352656574042669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/6294352656574042669'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/03/no-fluff-just-stuff-iphone-app.html' title='No Fluff Just Stuff iPhone App'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-Qe3IbRFsL4/S51ru8N8yvI/AAAAAAAAA50/JPoiK0Srkao/s72-c/nfjs_iphone_app_175x175.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-4271167427019306586</id><published>2010-03-13T11:00:00.000-08:00</published><updated>2010-03-13T00:42:01.659-08:00</updated><title type='text'>Embedding Jetty</title><content type='html'>Jetty has been a popular servlet container for a long time; but until now I really didn't need an embedded servlet container.  Now, I finally do and found many tutorials and guides.  However, I didn't have much luck at first.  I kept running into various conflicts.  Then I found the &lt;a href="http://blogs.webtide.com/janb/entry/jetty_runner"&gt;jetty runner&lt;/a&gt;.  This is the easiest way to do it.  It only requires &lt;a href="http://repo2.maven.org/maven2/org/mortbay/jetty/jetty-runner/"&gt;one jar file&lt;/a&gt;.  Then create a script such as:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;JETTY=lib/resource/jetty-runner-7.0.1.v20091125.jar&lt;br /&gt;&lt;br /&gt;DATA_DIR="$HOME/workspace/data/project"&lt;br /&gt;&lt;br /&gt;echo "DATA_DIR dir is $DATA_DIR"&lt;br /&gt;echo "Running Jetty..."&lt;br /&gt;&lt;br /&gt;java -jar $JETTY --path / build/webapps/ROOT --path /s $DATA_DIR/s&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-4271167427019306586?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/4271167427019306586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/03/embedding-jetty.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/4271167427019306586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/4271167427019306586'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/03/embedding-jetty.html' title='Embedding Jetty'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-2679346125216719895</id><published>2010-02-16T07:45:00.000-08:00</published><updated>2010-02-16T08:03:41.133-08:00</updated><title type='text'>New Destination Event: Über Conf - Denver, CO - June 14-17, 2010</title><content type='html'>I'm excited that &lt;a href="http://www.nofluffjuststuff.com"&gt;No Fluff Just Stuff&lt;/a&gt; will be hosting &lt;a href="http://uberconf.com"&gt;Über Conf&lt;/a&gt; in June!  I created the web site for this event.&lt;br /&gt;&lt;br /&gt;This will be an awesome tech conference.  It's target audience are the "alpha geeks"... the experienced developers who solve difficult problems and create cool tech.  &lt;br /&gt;&lt;br /&gt;It will be a big event, with 7 concurrent sessions and over 100 total sessions to choose from.  This includes a big line-up of hands on workshops.  &lt;br /&gt;&lt;br /&gt;If you register for the special iPad seminar, you will receive an Apple iPad!  That's pretty cool.  It's a great opportunity to jump into an exciting technology.&lt;br /&gt;&lt;br /&gt;Plus it's in Denver in June.  Colorado is a beautiful place and June is a great time to visit.  If you're not from here, be sure to book a few extra days and visit the mountains.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://uberconf.com"&gt;&lt;img src="http://uberconf.com/s/images/promo/Westin_Westminster_2_med.jpg" alt="Westin Westminster"/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;&lt;a style="color: #CC0000;" href="http://uberconf.com"&gt;Über Conf Event Details&lt;/a&gt;&lt;/h3&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-2679346125216719895?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/2679346125216719895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2010/02/new-destination-event-uber-conf-denver.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2679346125216719895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2679346125216719895'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2010/02/new-destination-event-uber-conf-denver.html' title='New Destination Event: Über Conf - Denver, CO - June 14-17, 2010'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-8588342339996301342</id><published>2009-12-17T11:43:00.000-08:00</published><updated>2009-12-17T14:19:50.378-08:00</updated><title type='text'>Creating Screencasts with OS X Snow Leopard</title><content type='html'>Snow Leopard includes all of the tools you need to create a high quality screencast.  However, you have to get the settings right or the video quality will be poor.&lt;br /&gt;&lt;br /&gt;Steps:&lt;br /&gt;1) Capture Screencast with QuickTime Player&lt;br /&gt;2) Edit with iMovie&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Capture Screencast with QuickTime Player&lt;/h3&gt;&lt;br /&gt;This is pretty straightforward.  &lt;br /&gt;&lt;br /&gt;First, change your display resolution to 1024x768.  You want to capture the screencast with the same resolution it will be encoded and viewed in.  &lt;br /&gt;&lt;br /&gt;Next, launch QuickTime Player and select: File &gt; New Screen Recording&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-Qe3IbRFsL4/SyqNLZOT1bI/AAAAAAAAA4c/VAsI4OV4Vf8/s1600-h/new_screencast.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 154px;" src="http://1.bp.blogspot.com/_-Qe3IbRFsL4/SyqNLZOT1bI/AAAAAAAAA4c/VAsI4OV4Vf8/s320/new_screencast.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5416296728755426738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Be sure to specify your microphone, select High Quality, and specify where you want to save the file.  My internal microphone works well, but you may want to use an external mic.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-Qe3IbRFsL4/SyqM6VBEIDI/AAAAAAAAA4M/AW3huNQpqa8/s1600-h/screencast_settings.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 154px;" src="http://2.bp.blogspot.com/_-Qe3IbRFsL4/SyqM6VBEIDI/AAAAAAAAA4M/AW3huNQpqa8/s320/screencast_settings.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5416296435568353330" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now you are set to capture the screencast.  Do a short test first to ensure the audio level sounds good.  Create your screencast clips.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Edit your Screencast with iMovie&lt;/h3&gt;&lt;br /&gt;The most important step in iMovie is to select the "HDV 720p" format when creating the iMovie project.  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-Qe3IbRFsL4/SyqPTKgURMI/AAAAAAAAA4s/3j1vxjKyDCI/s1600-h/iMovie_create_project.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_-Qe3IbRFsL4/SyqPTKgURMI/AAAAAAAAA4s/3j1vxjKyDCI/s320/iMovie_create_project.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5416299061266629826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I won't go into the details of editing with iMovie.  It is fairly easy to figure out.&lt;br /&gt;&lt;br /&gt;1) drag your screencast clips into the project.  &lt;br /&gt;2) drag them into the correct play sequence editor at the bottom&lt;br /&gt;3) trim your clips&lt;br /&gt;4) add titles&lt;br /&gt;5) Export the video&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Trim Clips&lt;/h4&gt;   &lt;br /&gt;In the editor, find the position where you want to trim a clip.  Select Edit &gt; Split Video Clip at Playhead.  Then delete the piece you wish to trim out.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Add a Title&lt;/h4&gt;&lt;br /&gt;Click the "Editing" tab on the lower right toolbar.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-Qe3IbRFsL4/SyqQd5UKBJI/AAAAAAAAA40/ZP1XXsqmVG0/s1600-h/add_title.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 149px;" src="http://2.bp.blogspot.com/_-Qe3IbRFsL4/SyqQd5UKBJI/AAAAAAAAA40/ZP1XXsqmVG0/s320/add_title.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5416300345142412434" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Export the Video&lt;/h4&gt;&lt;br /&gt;After your editing is complete you are ready to create the final video.  It is important to use the correct settings here.&lt;br /&gt;&lt;br /&gt;To start, select "Share &gt; Share" from the menubar.  Select "Expert Settings".  I export my screencasts as MPEG-4.  Most video on the web is currently streamed in flash video.  I have Flash 8 on my Mac.  However, something is not compatible and the audio cuts out when I encode as Flash.  I do the Flash encoding on another machine or allow my video host to do the encoding.  You may be able to skip MPEG-4 and encode straight to Flash.  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-Qe3IbRFsL4/SyqUE_hD8PI/AAAAAAAAA48/1gLK0I45_AA/s1600-h/export_as_mpg4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 258px;" src="http://3.bp.blogspot.com/_-Qe3IbRFsL4/SyqUE_hD8PI/AAAAAAAAA48/1gLK0I45_AA/s320/export_as_mpg4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5416304315356934386" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Click on the "Options" button to specify encoding settings. These are the encoding settings I use.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-Qe3IbRFsL4/SyqUii_D-mI/AAAAAAAAA5E/k2RMGuPHHeg/s1600-h/mpeg4_encoding_settings.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 304px;" src="http://2.bp.blogspot.com/_-Qe3IbRFsL4/SyqUii_D-mI/AAAAAAAAA5E/k2RMGuPHHeg/s320/mpeg4_encoding_settings.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5416304823094213218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Click the "Video Options" button to specify multi-pass encoding mode.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-Qe3IbRFsL4/SyqVRwZWvpI/AAAAAAAAA5U/tVuXVsMmNAc/s1600-h/mpeg4_multipass.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 188px;" src="http://2.bp.blogspot.com/_-Qe3IbRFsL4/SyqVRwZWvpI/AAAAAAAAA5U/tVuXVsMmNAc/s320/mpeg4_multipass.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5416305634148007570" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Audio Settings&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-Qe3IbRFsL4/SyqU4RLBRHI/AAAAAAAAA5M/wMw9HTb8z4k/s1600-h/mpeg4_audio.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 302px;" src="http://3.bp.blogspot.com/_-Qe3IbRFsL4/SyqU4RLBRHI/AAAAAAAAA5M/wMw9HTb8z4k/s320/mpeg4_audio.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5416305196269651058" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That's it.  Click Save to start the encoding process.  It may take a while.&lt;br /&gt;&lt;br /&gt;I am not a video professional.  If you have tips on improving this process, your comments are welcome!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-8588342339996301342?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/8588342339996301342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2009/12/creating-screencasts-with-os-x-snow.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/8588342339996301342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/8588342339996301342'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2009/12/creating-screencasts-with-os-x-snow.html' title='Creating Screencasts with OS X Snow Leopard'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-Qe3IbRFsL4/SyqNLZOT1bI/AAAAAAAAA4c/VAsI4OV4Vf8/s72-c/new_screencast.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-2179425814017663664</id><published>2009-11-24T21:51:00.000-08:00</published><updated>2009-12-16T12:11:07.610-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone Application'/><title type='text'>FortuneNix iPhone App</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-Qe3IbRFsL4/SwzGTEYqz2I/AAAAAAAAA3Q/qb3RqDsklDc/s1600/FortuneNix.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 170px; height: 320px;" src="http://1.bp.blogspot.com/_-Qe3IbRFsL4/SwzGTEYqz2I/AAAAAAAAA3Q/qb3RqDsklDc/s320/FortuneNix.jpg" alt="" id="BLOGGER_PHOTO_ID_5407915283462147938" border="0" /&gt;&lt;/a&gt;Looking for a quick laugh?  FortuneNix is a simple program that displays a random message from a database of quotations.  If you turn on the "potentially offensive" option, there are plenty of racy quotations sure to amuse you!  Go ahead try the limericks.. "There once was a man from Nantucket..." you get the idea.&lt;br /&gt;&lt;br /&gt;Based on the popular Unix fortune program, many of the quotations have a particular appeal to software developers and system admins who have worked with Unix.  This little app will provide entertainment for a long time to come.  There are over 17,000 quotes in the database. &lt;br /&gt;&lt;br /&gt;Do you sometimes feel ill at ease when you've been away from the command line for too long?   This little app will take you back momentarily.  It also has a few modern touches of usability.  It allows you to browse categories of quotations, create a list of your favorites, and send them via email.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;margin: 10px 0 20px 0;font-family: Arial;"&gt;&lt;a style="color: #CC0000;text-decoration: underline;" href="itms://itunes.apple.com/us/app/fortunenix/id342638538?mt=8"&gt;Get the FortuneNix App Here&lt;/a&gt;&lt;/h3&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-2179425814017663664?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/2179425814017663664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2009/11/fortunenix-iphone-app.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2179425814017663664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/2179425814017663664'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2009/11/fortunenix-iphone-app.html' title='FortuneNix iPhone App'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-Qe3IbRFsL4/SwzGTEYqz2I/AAAAAAAAA3Q/qb3RqDsklDc/s72-c/FortuneNix.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-3291582802096387293</id><published>2009-11-24T09:00:00.000-08:00</published><updated>2009-11-24T10:06:30.955-08:00</updated><title type='text'>Use Closures for Transactions in Groovy</title><content type='html'>Groovy closures are a handy tool for making your code reusable.  One place I have found them particularly useful is in executing database transactions.  &lt;br /&gt;&lt;br /&gt;Ideally, transactions management should be handled at the level of AOP, filter, or interceptor that has no knowledge of a specific action execution.  However, it is often necessary to implement transactions in a specific isolated scope; such as when you have to process a large collection of records.  In such a case, when you need to commit your transaction for each record processed; your code is likely to always use the same cut and paste transaction management code.&lt;br /&gt;&lt;br /&gt;In a typical Java application that uses Hibernate, you will often see code like this repeated through out the application:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;Transaction tr = session.beginTransaction()&lt;br /&gt;try {&lt;br /&gt; // update some object&lt;br /&gt; book.title = "Foo Bar"&lt;br /&gt; session.save(book)&lt;br /&gt; &lt;br /&gt; tr.commit()&lt;br /&gt;} catch(Throwable t) {&lt;br /&gt; tr.rollback()&lt;br /&gt; log.error("ERROR",t)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It's always the same code, but grandpa's Java syntax doesn't make it easy to reuse this code.  With Groovy, you write this code once and wrap your code in a closure anytime you require a transaction. &lt;br /&gt;&lt;br /&gt;So a new execution looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;def closure = {&lt;br /&gt; // update some object&lt;br /&gt; book.title = "Foo Bar"&lt;br /&gt; session.save(book)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;doWithTransaction(closure)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here is your reusable transaction management code:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;def doWithTransaction = { def closure -&gt;&lt;br /&gt;&lt;br /&gt; Transaction tr = session.beginTransaction()&lt;br /&gt; try {&lt;br /&gt;  closure()&lt;br /&gt;  tr.commit()&lt;br /&gt; } catch(Throwable t) {&lt;br /&gt;  tr.rollback()&lt;br /&gt;  log.error("ERROR",t)&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is just another way Groovy closures can help clean up your code base.  Using closures in this manner makes it easier to increase your code coverage, since you will only need to write one test case to test the reused transaction code.  If you have large code base, these small changes can really help.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-3291582802096387293?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/3291582802096387293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2009/11/use-closures-for-transactions-in-groovy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/3291582802096387293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/3291582802096387293'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2009/11/use-closures-for-transactions-in-groovy.html' title='Use Closures for Transactions in Groovy'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-6429237959637269079</id><published>2009-11-18T08:00:00.001-08:00</published><updated>2009-11-18T08:00:02.363-08:00</updated><title type='text'>Case Study: Migrating a Java Web App to Groovy &amp; TDD</title><content type='html'>In this post, I will touch on the steps I took to migrate the &lt;a href="http://www.nofluffjuststuff.com/"&gt;nofluffjuststuff.com&lt;/a&gt; code base to Groovy.  Next to quitting a job that sucks, migrating to Test Driven Development &amp; Groovy is just about the best thing a Java developer can do to improve life on the job. &lt;br /&gt;&lt;br /&gt;I wont go into the technical details.  I simply want to join the chorus of those  highlighting the benefits of Groovy &amp; TDD and show some results. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;High-level Steps:&lt;/span&gt;&lt;br /&gt;1. Implement Automated Unit Testing w/ Groovy &lt;br /&gt;2. Achieve a high level of code coverage (+70% should be good)&lt;br /&gt;3. Start changing application .java files to .groovy&lt;br /&gt;4. Remove getters and setters&lt;br /&gt;5. Remove dead code&lt;br /&gt;6. Use closures&lt;br /&gt;7. Use more Groovy sugar such as file and XML processing&lt;br /&gt;8. refactor, test.. repeat&lt;br /&gt;&lt;br /&gt;This type of migration is best completed in an ongoing, incremental process.  Shoot for constant improvement.&lt;br /&gt;&lt;br /&gt;This "legacy" java web app (launched 2004) was already pretty sexy. The stack: Sitemesh, Struts 2, Spring, Hibernate... lots of Open Source goodness. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Unit Testing and Code Coverage&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When using a dynamic language such as Groovy, it is absolutely critical that you have a high level of code coverage!  The Groovy compiler doesn't type check your code.  One typo and your app may be hosed.  However, type checking is a very weak test.  I would still work on a plain old Java app, but I won't work on a project that doesn't unit test.&lt;br /&gt;&lt;br /&gt;Purists argue for 100% code coverage.  I would shoot for that if I were starting a new application.  When you already have 20,000+ lines of code, reaching 100% coverage is difficult. &lt;br /&gt;&lt;br /&gt;I once sat in presentation by Rod Johnson and he said 70-80% is a good goal to shoot for... I'm not sure if he still stands by that, but my experience is that 70-80% coverage has made my life much easier and more productive.  I'm the sole developer of this project and I have zero QA staff... I deploy new features and updates almost daily so I really depend on automated testing. It allows me to sleep at night and keep my customer happy. &lt;br /&gt;&lt;br /&gt;I measure code coverage with &lt;a href="http://cobertura.sourceforge.net/"&gt;Cobertura&lt;/a&gt;.  It handles Groovy seamlessly.  You may also want to find a tool that will analyze your code base and stub out your unit test suite.&lt;br /&gt;&lt;br /&gt;The full force migration to Groovy started in February of 2008 around the time of the first &lt;a href="http://www.springone2gx.com/conference/new_orleans/2009/10/2gx/event_about"&gt;2GX&lt;/a&gt; conference.  That was a great event!  Unfortunately, I couldn't make it this year. I also did the web site for that event.  It was a separate Grails application with the JPA data model from this code base mixed in.&lt;br /&gt;&lt;br /&gt;At the start, I had nearly 20,000 lines of Java code and 71% code coverage.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwOSf9qv9hI/AAAAAAAAA3A/Yt6Cx-eb4wc/s1600/code_coverage_1.jpg"&gt;&lt;img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 99px;" src="http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwOSf9qv9hI/AAAAAAAAA3A/Yt6Cx-eb4wc/s320/code_coverage_1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5405325055602193938" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I keep a history of my code coverage reports.  Six month's later, I had 15,656 lines of code and 80% coverage.  A near 4000 line reduction.  We're always busy enhancing our sites, so I also added a LOT of new code in that time.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-Qe3IbRFsL4/SwOTVNEhp5I/AAAAAAAAA3I/uWPjHRgWlhY/s1600/code_coverage_2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 98px;" src="http://3.bp.blogspot.com/_-Qe3IbRFsL4/SwOTVNEhp5I/AAAAAAAAA3I/uWPjHRgWlhY/s320/code_coverage_2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5405325970269906834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now it's almost 2 years since the start and I have 18,712 lines and 83% coverage.  For most of this year I have usually maintained 85% coverage, so I've been slacking lately and need to spend a few days getting that number back up.  It's an ongoing process.. tracking the numbers is key!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Remove Getters and Setters&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The largest reduction in lines of code comes from removing getter and setter methods.  I started with my data model... turning my POJOs into POGOs.  Then I did the same to my Struts 2 action classes.  Sometimes I did major bursts of refactoring. Other times, I would just change Java to Groovy as I happened to be working in that area of code. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Remove Dead Code&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Business requirements change quickly, so does the code.  Over time, a fair amount of our code goes out of use.  Sometimes it is replaced by a new subsystem, sometimes certain parts of a web site just go away.  Removing dead code is good!  Dead code just sits around and stinks.  It really slows refactoring and maintenance of other parts of the code base. If you don't have a high percentage of unit testing, it is nearly impossible to remove dead code.  With a high level of coverage, you can rip it out with your IDEs refactoring tools.  The automated testing will give you confidence that everything still works.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Use closures&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At first, I really didn't understand closures.  I kept hearing about them, but as is typical of our industry things are often explained in a poor and complicated language.  Now, I love closures and use them all the time.&lt;br /&gt;&lt;br /&gt;I'm not a computer scientist, so I won't provide a "definition".  But I will attempt a simple explanation... &lt;br /&gt;&lt;br /&gt;1) they are like a method in that they contain a body of work or "behavior". &lt;br /&gt;2) they are assignable or interchangeable like a property&lt;br /&gt;&lt;br /&gt;Why is this good? Closures are an easy way to make behavior interchangeable.  This is especially useful for unit testing.  &lt;br /&gt;&lt;br /&gt;With pure Java it can be hard to unit test certain pieces of code; such as, those that perform long running operations or download content from the web.  You want your unit tests to be fast!  Place that specific long running piece of code in a closure.  It acts just like a method, but during unit testing you can interchange that closure with another closure that will quickly mock the piece of code.  &lt;br /&gt;&lt;br /&gt;This is the easiest way to do mocking and it really helps increase your code coverage numbers!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Refactor, Test... repeat&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is simply an ongoing process.  In the 2 years since this has started, I have introduced Groovy through out my work. The application build is done with Gant.  I have also simplified my deployments and other sys admin functions with Groovy scripts.  Groovy scripting is so much easier than writing shell scripts!  There was a time when all the steps required to build and deploy to my 4-7 web sites (they change often) would take as long as a half hour. Now it usually takes 2-3 minutes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What about Grails??&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Grails is a great framework. Starting out, I was hoping to migrate the Struts 2 application to a Grails app.  Grails had just launched version 1.0 and I had trouble integrating Struts 2 into a grails app.  They just didn't mesh at the time and I had way too much code to do a port.  Grails is moving along quickly, so the situation may be different now.  Someone should try shoving a Struts 2 app inside a Grails app... &lt;br /&gt;&lt;br /&gt;Fortunately, Groovy and Java work together seamlessly.  I don't believe it matters what your web framework is.. you can just start changing Java to Groovy... provided you have a comprehensive unit test suite!  Struts 2 is a great framework as well.  It's a dream compared to the homegrown craptastic frameworks most of us had only 5 years ago.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Learn It&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I learned Groovy by attending sessions at &lt;a href="http://www.nofluffjuststuff.com/"&gt;NFJS&lt;/a&gt;, &lt;a href="http://www.springone2gx.com/conference/new_orleans/2009/10/2gx/event_about"&gt;2GX&lt;/a&gt;, and reading &lt;a href="http://www.nofluffjuststuff.com/conference/speaker/scott_davis"&gt;Scott Davis's&lt;/a&gt; book &lt;a href="http://www.amazon.com/Groovy-Recipes-Greasing-Pragmatic-Programmers/dp/0978739299%3FSubscriptionId%3D0DF4GRF9MZ0ZP9X84F82%26tag%3Dnofljust-20%26linkCode%3Dsp1%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0978739299"&gt;Groovy Recipes&lt;/a&gt;.  The &lt;a href="http://www.amazon.com/Definitive-Guide-Grails-Second/dp/1590599950/ref=sr_1_2?ie=UTF8&amp;s=books&amp;qid=1258530122&amp;sr=1-2"&gt;The Definitive Guide to Grails&lt;/a&gt; and the &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; home page are quite good as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-6429237959637269079?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/6429237959637269079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2009/11/case-study-migrating-java-web-app-to.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/6429237959637269079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/6429237959637269079'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2009/11/case-study-migrating-java-web-app-to.html' title='Case Study: Migrating a Java Web App to Groovy &amp; TDD'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwOSf9qv9hI/AAAAAAAAA3A/Yt6Cx-eb4wc/s72-c/code_coverage_1.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2759245772859176868.post-3314790267345307775</id><published>2009-11-15T08:00:00.000-08:00</published><updated>2009-11-18T00:14:16.717-08:00</updated><title type='text'>New Blog</title><content type='html'>Welcome to my blog.  Hope you are not disappointed by the lack of content.  I created this blog to host information about my work as a software developer.&lt;br /&gt;&lt;br /&gt;I've been a Java developer since 1999.  Currently, my primary project is developing and managing &lt;a href="http://www.nofluffjuststuff.com/"&gt;nofluffjuststuff.com&lt;/a&gt; and related sites for the No Fluff Just Stuff Java Symposium Series (&lt;a href="http://www.springone2gx.com/"&gt;springone2gx.com&lt;/a&gt;, &lt;a href="http://www.therichwebexperience.com/"&gt;therichwebexperience.com&lt;/a&gt;, &lt;a href="http://www.jsfsummit.com/"&gt;jsfsummit.com&lt;/a&gt;, and &lt;a href="http://www.nfjsone.com/"&gt;nfjsone.com&lt;/a&gt;).  It has been a pleasure to work with NFJS since 2004. &lt;br /&gt;&lt;br /&gt;I find it very exciting to always be learning and working with new technologies!  Currently, I'm excited to be getting into iPhone development.  I hope to release my first app before the holidays.&lt;br /&gt;&lt;br /&gt;If you wish to find out more about me, you may do so on Facebook, Linked In, Flickr, and Twitter.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.facebook.com/people/Ben-Ellingson/519292795"&gt;&lt;img src="http://www.nofluffjuststuff.com/img/network/facebook-32.png"  /&gt;&lt;/a&gt;   &lt;a href="http://www.linkedin.com/pub/ben-ellingson/1/1b/299"&gt;&lt;img src="http://www.nofluffjuststuff.com/img/network/LinkedIn_32.png"/&gt;&lt;/a&gt;    &lt;a href="http://www.flickr.com/photos/benellingson/"&gt;&lt;img src="http://www.nofluffjuststuff.com/s/images/random/flickr_32.png" /&gt;&lt;/a&gt;    &lt;a href="http://twitter.com/benellingson"&gt;&lt;img src="http://www.nofluffjuststuff.com/s/images/random/twitter_32.png"/&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2759245772859176868-3314790267345307775?l=benellingson.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://benellingson.blogspot.com/feeds/3314790267345307775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://benellingson.blogspot.com/2009/11/new-blog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/3314790267345307775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2759245772859176868/posts/default/3314790267345307775'/><link rel='alternate' type='text/html' href='http://benellingson.blogspot.com/2009/11/new-blog.html' title='New Blog'/><author><name>benellingson</name><uri>http://www.blogger.com/profile/10726066570176798218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_-Qe3IbRFsL4/SwBRq2Rm13I/AAAAAAAAA2c/MIvjxH3Ybsg/s1600-R/4089935182_1925108855_o.jpg'/></author><thr:total>0</thr:total></entry></feed>
