<?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-1776345669994681097</id><updated>2011-12-12T06:17:28.492-06:00</updated><category term='eclipse'/><category term='android'/><category term='GWT'/><category term='JSP'/><category term='ABM'/><title type='text'>Stuff I keep Forgetting How to Do</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>29</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-3915232809096693093</id><published>2011-10-14T07:14:00.000-05:00</published><updated>2011-10-14T07:14:55.421-05:00</updated><title type='text'>Import Self Signed Certs</title><content type='html'>Day three of using self signed certs and I was tired of telling chrome to accept it.  Under the wrench menu there was an import certificate process.  However, for Ubunutu, what it really needed was importing them into &lt;a href="http://code.google.com/p/chromium/wiki/LinuxCertManagement"&gt;the OS keystore&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;First step, install the libnss3-tools:&lt;br /&gt;&lt;blockquote&gt;sudo apt-get install libnss3-tools&lt;/blockquote&gt;&lt;br /&gt;There is a mention on that page linked above that says the cert needs to be imported as a CA due to a bug.  On Natty Ubuntu it was not necessary.  I put the following function in my .bashrc&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;function trustCert() {&lt;br /&gt;    [ $# -ne 2 ] &amp;&amp; echo "you need to provide [certificate_nickname] and [certificate_filename]" &amp;&amp; return 1&lt;br /&gt;    certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n $1 -i $2&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-3915232809096693093?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/3915232809096693093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=3915232809096693093' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/3915232809096693093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/3915232809096693093'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2011/10/import-self-signed-certs.html' title='Import Self Signed Certs'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-7817416396542667384</id><published>2011-06-10T08:56:00.000-05:00</published><updated>2011-06-10T08:56:43.984-05:00</updated><title type='text'>Gradle Dependencies</title><content type='html'>I was looking for the command to tell gradle to list the project dependencies (think maven dependency:tree).  I came across &lt;a href="http://issues.gradle.org/browse/GRADLE-299"&gt;this closed bug&lt;/a&gt;.  Annoyingly that bug does not say how to actually &lt;b&gt;output&lt;/b&gt; the listing.&lt;br /&gt;&lt;br /&gt;Well, it's a command line option (run gradle --help) that was deprecated in favor of:&lt;br /&gt;&lt;blockquote&gt;gradle dependencies&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-7817416396542667384?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/7817416396542667384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=7817416396542667384' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7817416396542667384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7817416396542667384'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2011/06/gradle-dependencies.html' title='Gradle Dependencies'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-644973884147060069</id><published>2011-05-31T11:47:00.000-05:00</published><updated>2011-05-31T11:47:46.035-05:00</updated><title type='text'>Architecting and Building A startup</title><content type='html'>This is not my usual flavor of posts in this space.  However, it seems like a good place to mention that my users of Book Mobile have been feeling even more abandoned lately as I've left the corporate world to Architect and build a startup.  Stealth mode requires that I say nothing about the startup or it's architecture.&lt;br /&gt;&lt;br /&gt;Hopefully those Book Mobile users understand the nature of spare-time-projects and how that spare time ebbs and flows.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-644973884147060069?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/644973884147060069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=644973884147060069' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/644973884147060069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/644973884147060069'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2011/05/architecting-and-building-startup.html' title='Architecting and Building A startup'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-4526180847089764244</id><published>2011-01-26T23:35:00.001-06:00</published><updated>2011-01-27T20:11:09.004-06:00</updated><title type='text'>Ubuntu Maverick Meerkat Android UDEV Settings</title><content type='html'>Thank you &lt;a href="http://esausilva.com/2010/05/13/setting-up-adbusb-drivers-for-android-devices-in-linux-ubuntu/"&gt;Esua Silva&lt;/a&gt; for referencing the Maverick udev syntax for my 70-android.rules file.  I have a nexus one so of course my vendor id is 18D1:&lt;br /&gt;&lt;blockquote&gt;SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666"&lt;/blockquote&gt;&lt;br /&gt;The syntax change from Lucid to Maverick should have been easier to find.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-4526180847089764244?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/4526180847089764244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=4526180847089764244' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/4526180847089764244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/4526180847089764244'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2011/01/ubuntu-maverick-meerkat-android-udev.html' title='Ubuntu Maverick Meerkat Android UDEV Settings'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-6564606391425617690</id><published>2010-08-29T09:26:00.000-05:00</published><updated>2010-08-29T09:26:42.810-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ABM'/><title type='text'>Android Book Mobile Version 1.8</title><content type='html'>I've finally released my first cut at Amazon integration.  This will hopefully be THE revenue stream.  As always Book Mobile is free and ad-free.  The search result screen now includes a button to open a web browser with the Amazon page for the current book.  As part of this integration I now, for the first time, have some metrics about how much the application is being used.  All of this is completely anonymous!  The last thing I want is the responsibility keeping personal data safe from attack.&lt;br /&gt;&lt;br /&gt;In the first 24 hours there have been 664 books successfully looked up.  The sad part is that only 7 of them where clicked through to Amazon and non of those users bought anything.  So far the only revenue is from last week when my wife used a beta version to buy me another Elmore Leonard paperback -- thanks honey!&lt;br /&gt;&lt;br /&gt;This release included a large refactoring of the result screen where most of the error reports are occurring.  Please update so I can fix any remaining issues!  Better yet, if you are running Froyo you can look for that auto update checkbox on the market application update screen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-6564606391425617690?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/6564606391425617690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=6564606391425617690' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6564606391425617690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6564606391425617690'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2010/08/android-book-mobile-version-18.html' title='Android Book Mobile Version 1.8'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-6055810247562945632</id><published>2010-07-14T15:01:00.000-05:00</published><updated>2010-07-14T15:01:49.901-05:00</updated><title type='text'>Microsoft Office Has one Cool Feature</title><content type='html'>I know that Microsoft Outlook has many pundits.  I'm one of them.  But that mail client has one thing going for it.  When I type "doe snot" when I really meant "does not" -- Outlook would catch the typo and put the "s" where it belonged.  Mind you, I don't think this is a redeeming feature.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-6055810247562945632?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/6055810247562945632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=6055810247562945632' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6055810247562945632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6055810247562945632'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2010/07/microsoft-office-has-one-cool-feature.html' title='Microsoft Office Has one Cool Feature'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-7430001405725181978</id><published>2010-04-21T13:33:00.003-05:00</published><updated>2010-04-21T13:37:33.710-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>Eclipse Search in Debug View</title><content type='html'>Well, I was debugging Glassfish via a remote connection and needed to find a particular thread to pause.  Of course I was looking for the http worker threads.  Scanning that long list of threads is just to painful.  So I thought, "Can I search this?"  I hit F5, and low-n-behold a search window comes up listing the threads.  I type "*HttpWorkerThread", select one, and am returned to the Debug view with the same thread selected.&lt;br /&gt;&lt;br /&gt;Thank you Eclipse.  Thank you for just working -- the way software should.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-7430001405725181978?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/7430001405725181978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=7430001405725181978' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7430001405725181978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7430001405725181978'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2010/04/eclipse-search-in-debug-view.html' title='Eclipse Search in Debug View'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-4858142100993906343</id><published>2010-01-28T10:19:00.003-06:00</published><updated>2010-01-28T10:27:48.671-06:00</updated><title type='text'>The Downside of Touch Screen Devices</title><content type='html'>The downside of touch devices is that my autonomic response is evolving to interact with every gadgets screen.  I just tried swiping my finger across the screen of my 5G iPod.  &lt;br /&gt;&lt;br /&gt;I'll be glad when the family budget allows me to upgrade all of the iPods and my wife's phone to a touch screen.  Maybe by then &lt;a href="http://www.citizenwatch.com/"&gt;Citizen &lt;/a&gt;watch will have a touchscreen to replace those buttons on the side of my current model.  I'm sure you can think of something that needs a touch screen.  It might be interesting to play with one of those new iPads.  Every time I've used a touch screen computer in the past I found it lacking the precision I desire.  The precision that I'm used to from a mouse.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-4858142100993906343?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/4858142100993906343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=4858142100993906343' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/4858142100993906343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/4858142100993906343'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2010/01/downside-of-touch-screen-devices.html' title='The Downside of Touch Screen Devices'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-8282481204561405668</id><published>2009-10-06T10:06:00.005-05:00</published><updated>2009-10-07T07:51:07.134-05:00</updated><title type='text'>Continuous Integration</title><content type='html'>I've worked in environments with continuous integration for nine years.  I introduced the concept at 2 of the 4 companies I worked at over that time.  Hopefully everyone developing in an environment supported by continuous integration already takes build pass/fail seriously.  If not,  I suggest a moment of personal reflection upon your projects continuous integration server.  I suggest that everyone might look at the health across multiple projects and multiple builds to assess how well they are doing to keep the projects green.  What is your rough estimate of build success on the builds that your commits triggered?  In Team City, find the “My Changes” tab at the top.  Expand all three (at least I have three) sections. In CruiseControl, hmmm? I'm not sure anymore.&lt;br /&gt;&lt;br /&gt;I am not trying to incite any sort of competition over who can reach 100% triggered build success.  I only suggest that we might think about our personal goals.  We might challenge ourselves to never cause a build failure.  To aspire to 100% success is wrong.  There are going to be a few "oops".  There are going to be some environment problems.&lt;br /&gt;&lt;br /&gt;Project management should always be looking at the percentage of failed builds.  Also looking at the volume of commits and the size of commits.  Particularly just prior to a release.  Continuous integration is a great tool like any other -- the value derived is based on how it is used.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-8282481204561405668?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/8282481204561405668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=8282481204561405668' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/8282481204561405668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/8282481204561405668'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/10/continuous-integration.html' title='Continuous Integration'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-2327640349688296608</id><published>2009-09-30T22:41:00.002-05:00</published><updated>2009-09-30T22:55:11.290-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSP'/><category scheme='http://www.blogger.com/atom/ns#' term='GWT'/><title type='text'>Mixing JSP 2.0 with GWT</title><content type='html'>I've just overcome a pesky litle problem between JSP 2.0 and GWT.  I have my JSPs in xml format: &lt;code&gt;&amp;lt;jsp:root ...&gt;&lt;/code&gt;.  You are likely aware that this is a bit aggressive about removing whitespace from the resulting html.  This includes the transformation of empty body tags into bodyless tags.  Ergo this&lt;br /&gt;    &lt;code&gt;&amp;lt;div id="footer"&gt;&amp;lt;/div&gt;&lt;/code&gt;&lt;br /&gt;becomes this&lt;br /&gt;    &lt;code&gt;&amp;lt;div id="footer"/&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now that second one was confusing firefox on my linux workstation.  Likely on your platform as well.  This is just like the old days when we fought with &lt;code&gt;&amp;lt;script src="thefile.js" /&gt;&lt;/code&gt; tags to make sure they keep their separate closing tag.&lt;br /&gt;&lt;br /&gt;The solution is just to drop a comment into the previously empty body&lt;br /&gt;    &lt;code&gt;&amp;lt;div id="footer"&gt;&amp;lt;![CDATA[&amp;lt;!-- --&gt;]]&gt;&amp;lt;/div&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://rbtech.blogspot.com/2007/06/gwt-and-jsp-20-oh-pain.html/xml"&gt;Thank you Ramon&lt;/a&gt;, for pointing me down the path.  It's been a long time away from servlet code.  It should not have taken me as long as it did to remember this problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-2327640349688296608?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/2327640349688296608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=2327640349688296608' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2327640349688296608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2327640349688296608'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/09/mixing-jsp-20-with-gwt.html' title='Mixing JSP 2.0 with GWT'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-7427322243847390911</id><published>2009-09-06T21:58:00.006-05:00</published><updated>2010-01-02T12:34:28.330-06:00</updated><title type='text'>Android Book Mobile (1 week later)</title><content type='html'>It's been a great first week for ABM on the market.  Over 1,400 downloads and still carrying a 4 star rating!  Here is a screen shot of the Android Market -- Developer Console.  It shows all the applications you have published with their current stats.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_LX0ty8ZcDsc/SqR32KgAkxI/AAAAAAAAAQk/TQVrSi13xtI/s1600-h/androidmarket_bookMobile_wk1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 17px;" src="http://3.bp.blogspot.com/_LX0ty8ZcDsc/SqR32KgAkxI/AAAAAAAAAQk/TQVrSi13xtI/s400/androidmarket_bookMobile_wk1.png" alt="" id="BLOGGER_PHOTO_ID_5378555627402466066" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;One statistic that would be great if I knew how often people are using it.  If I had my own server-side to the application I could gather that statistic myself.  But alas, the data being stored at books.google.com, and the reviews coming from goodreads.com, I don't know how much they are using it.  I fully expect someone will tell me their phone ran out of memory trying to load their full library.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-7427322243847390911?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/7427322243847390911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=7427322243847390911' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7427322243847390911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7427322243847390911'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/09/android-book-mobile-1-week-later.html' title='Android Book Mobile (1 week later)'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_LX0ty8ZcDsc/SqR32KgAkxI/AAAAAAAAAQk/TQVrSi13xtI/s72-c/androidmarket_bookMobile_wk1.png' height='72' width='72'/><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-2015486769568656616</id><published>2009-08-29T06:07:00.003-05:00</published><updated>2009-08-29T06:22:25.907-05:00</updated><title type='text'>Android Book Mobile</title><content type='html'>I entered my Android application into the &lt;a href="http://http//code.google.com/android/adc/"&gt;Android Developer Challenge II&lt;/a&gt;.  You can read more about what "Book Mobile" does and my thoughts behind the name over at the &lt;a href="http://androidbookmobile.appspot.com/"&gt;product website&lt;/a&gt;.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I've integrated the Google book api into Android.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I use the &lt;a href="http://http//www.goodreads.com/api"&gt;GoodReads&lt;/a&gt; api to get reviews for books.  &lt;/li&gt;&lt;li&gt;I integrated with &lt;a href="http://code.google.com/p/zxing/"&gt;zxing&lt;/a&gt; for barcode scanning to read ISBNs.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Because of this &lt;a href="http://code.google.com/p/android/issues/detail?id=1073"&gt;missing feature in Android&lt;/a&gt; I had to draft my own login dialog for users to enter their google account credentials.&lt;/li&gt;&lt;/ul&gt;Now for the frustrating part.  How they setup the registration/entry process to the ADC means if I want my application available on the market, I have to repackage.  This means changing the AndroidManifest.xml and refactoring all the code to have a new package structure.  That doesn't seem so bad, right?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-2015486769568656616?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/2015486769568656616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=2015486769568656616' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2015486769568656616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2015486769568656616'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/08/android-book-mobile.html' title='Android Book Mobile'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-274166259213034326</id><published>2009-08-27T09:02:00.003-05:00</published><updated>2009-08-27T09:37:07.487-05:00</updated><title type='text'>Launch Explorer.exe from Cygwin</title><content type='html'>Working in cygwin, I often need an explorer window to my current directory or a sub-directory there of.  I called this script expl.sh.&lt;br /&gt;&lt;blockquote&gt;#!/bin/bash&lt;br /&gt;export p=`pwd`&lt;br /&gt;export pc=`cygpath -w $p/$1`&lt;br /&gt;explorer.exe /root,$pc &amp;amp;&lt;/blockquote&gt;Once you have this the directory on your path where you keep your scripts: perhaps ~/scripts:&lt;br /&gt;expl.sh&lt;br /&gt;expl.sh some/sub/directory&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-274166259213034326?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/274166259213034326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=274166259213034326' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/274166259213034326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/274166259213034326'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/08/launch-explorerexe-from-cygwin.html' title='Launch Explorer.exe from Cygwin'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-3026934300871467483</id><published>2009-08-24T22:01:00.003-05:00</published><updated>2009-08-24T22:07:37.500-05:00</updated><title type='text'>Google App Engine and GWT</title><content type='html'>Well, I started poking around with Goole app engine in Eclipse.  By default they want to use GWT.  fine.  Someone once said, "when drinking the tainted cool-aid you might as well eat the cookie too." (if no one said it then I just did)&lt;br /&gt;&lt;br /&gt;Well, I develop on Ubuntu and immediately ran into an UnsatisfiedLinkError.&lt;br /&gt;&lt;blockquote&gt;** Unable to load Mozilla for hosted mode **&lt;br /&gt;java.lang.UnsatisfiedLinkError: /home/user/projects/gwt-linux-1.5.3&lt;br /&gt;/mozilla-1.7.12/libxpcom.so: libstdc++.so.5:&lt;br /&gt;&lt;/blockquote&gt;Thankfully, &lt;a href="http://blog.scisurfer.com/2009/07/unable-to-load-mozilla-for-hosted-mode.html"&gt;this was the first hit&lt;/a&gt; on by search.  Thank you&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-3026934300871467483?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/3026934300871467483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=3026934300871467483' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/3026934300871467483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/3026934300871467483'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/08/google-app-engine-and-gwt.html' title='Google App Engine and GWT'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-5623530837625867919</id><published>2009-08-03T10:57:00.002-05:00</published><updated>2009-08-03T11:05:37.541-05:00</updated><title type='text'>When to Refactor</title><content type='html'>It's common knowledge that you don't write code in a software project to solve future problems.  Don't implement code that is not needed.&lt;br /&gt;&lt;br /&gt;It occurred to me that the inverse is true for refactoring.  I will not delay a refactor because we &lt;span style="font-weight: bold;"&gt;expect&lt;/span&gt; to have a requirement that will make it obsolete.  You never know which features/tasks will be canceled or delayed.  You should ask yourself, "How long am I willing to support this ugly code?"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-5623530837625867919?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/5623530837625867919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=5623530837625867919' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/5623530837625867919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/5623530837625867919'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/08/when-to-refactor.html' title='When to Refactor'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-2320901509830792427</id><published>2009-05-12T22:39:00.005-05:00</published><updated>2009-05-12T22:58:18.991-05:00</updated><title type='text'>Subversive Eclipse on Jaunty Ubuntu</title><content type='html'>I got all obsessed over the weekend.  I needed stable sound from my laptop.  I mean really, who can code without music!?  I don't want to talk about that.  I had a painful path form Hardy to Jaunty.  But that's not why I'm posting.  &lt;br /&gt;&lt;br /&gt;After a complete re-install of Ubuntu I was reinstalling Eclipse and Subversive.  It failed.  The "SVN Connectors" drop down was empty.  Turned out I fell victim to a bad link over to Polarion.  That was answered &lt;a href="http://stackoverflow.com/questions/139055/subversive-connectors-not-working-with-newest-ganymede-update/143379#143379"&gt;over on stackoverflow&lt;/a&gt;.  As stated in that answer, this is the right update site url to get the connectors from Polarion: http://www.polarion.org/projects/subversive/download/eclipse/2.0/update-site/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I wanted to use the javaHL connector, so I also &lt;a href="http://http://lorand.somogyi.name/2008/08/subversive-with-javahl-under-ubuntu/"&gt;needed this step&lt;/a&gt;. &lt;ul&gt;&lt;br /&gt;&lt;li&gt;sudo apt-get install libsvn-java&lt;br /&gt;&lt;li&gt;put "-Djava.library.path=/usr/lib/jni" in eclipse.ini&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt; &lt;br /&gt;Thanks guys/gals.  Hopefully I won't forget how to do this stuff.  (next time an OC urge strikes to set myself back 3 days)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-2320901509830792427?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/2320901509830792427/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=2320901509830792427' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2320901509830792427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2320901509830792427'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/05/subversive-eclipse-on-jaunty-ubuntu.html' title='Subversive Eclipse on Jaunty Ubuntu'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-8750827614758156568</id><published>2009-03-01T06:26:00.004-06:00</published><updated>2009-03-01T06:49:09.791-06:00</updated><title type='text'>J2EE Connector Architecture</title><content type='html'>J2EE Connector Architecture (JCA) is a little used aspect of J2EE that is probably now relegated to obscurity due to the popularity of web services.  It is however a viable solution to many problems.  You can still find it &lt;a href="http://java.sun.com/j2ee/connector/"&gt;documented at sun&lt;/a&gt;.  You can also rather nicely &lt;a href="http://static.springframework.org/spring/docs/2.0.x/reference/cci.html"&gt;integrate Spring&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I put this short presentation together.  Contact me if you would like the three Eclipse projects.&lt;br /&gt;&lt;iframe src='http://docs.google.com/EmbedSlideshow?docid=dg6hrt89_40cmsn2hfz' frameborder='0' width='410' height='342'&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-8750827614758156568?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/8750827614758156568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=8750827614758156568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/8750827614758156568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/8750827614758156568'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/03/j2ee-connector-architecture.html' title='J2EE Connector Architecture'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-2889930002923105931</id><published>2009-02-17T20:49:00.005-06:00</published><updated>2009-02-17T21:25:14.639-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Android Custom Component Merge</title><content type='html'>I created my &lt;a href="http://stuffikeepforgettinghowtodo.blogspot.com/2009/01/android-view-xml.html"&gt;custom component that extends LinearLayout&lt;/a&gt;.  In that post I show that the root element of the components XML is a &amp;lt;LinearLayout ...&gt; element.  That ended up getting in the way.  When the LayoutInflater built the view in my Java &lt;code&gt;PersonComposite extends LinearLayout&lt;/code&gt; the default behavior was that my java class now had one child, the LinearLayout that is the root of the XML.  This meant that each use of &amp;lt;my.app.PersonComposite ...&gt; in other view XML would never apply configuration to the Linearlayout that has any effect.&lt;br /&gt;&lt;br /&gt;Wow.  Even I don't understand that.  Let's try this way. The LayoutInflater, actually created the following structure (details omitted for brevity):&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&amp;lt;LinearLayout &gt;&lt;br /&gt;    &amp;lt;LinearLayout &gt;&lt;br /&gt;       &amp;lt;TextView .../&gt;&lt;br /&gt;       &amp;lt;TextView .../&gt;&lt;br /&gt;    &amp;lt;/LinearLayout&gt;&lt;br /&gt;&amp;lt;/LinearLayout&gt;&lt;/pre&gt;&lt;/blockquote&gt;So any attempts to use the component like this would never change the orientation of the two nested TextView Components because the configuration was applied to the outer LinearLayout: &lt;blockquote&gt;&lt;pre&gt;&amp;lt;my.app.PersonComposite&lt;br /&gt;   android:id="@+id/person"&lt;br /&gt;   android:orientation="vertical"&lt;br /&gt;/&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Solve this problem by using &amp;lt;merge&gt; as the root element.  And make sure you invoke LayoutInflater:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);&lt;br /&gt;View inflatedView = inflater.inflate(R.layout.person_composite, this);&lt;/blockquote&gt;Now the person_composite.xml looks something like this:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&amp;lt;merge xmlns:android="http://schemas.android.com/apk/res/android" &gt;&lt;br /&gt;       &amp;lt;TextView .../&gt;&lt;br /&gt;       &amp;lt;TextView .../&gt;&lt;br /&gt;&amp;lt;/merge&gt;&lt;/pre&gt;&lt;/blockquote&gt;You can see how this works by getting the &lt;a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=tree;f=core/res/res/drawable;hb=HEAD"&gt;android source&lt;/a&gt; from git and looking at the source code for the &lt;code&gt;LayoutInflater.inflate&lt;/code&gt; method.  then search that same source tree for an xml that uses &amp;lt;merge&gt; as the root element.  You'll find more than one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-2889930002923105931?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/2889930002923105931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=2889930002923105931' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2889930002923105931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2889930002923105931'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/02/android-custom-component-merge.html' title='Android Custom Component Merge'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-3348278742500339382</id><published>2009-02-08T07:09:00.007-06:00</published><updated>2009-02-08T08:03:33.056-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Unit Test Your Custom Parcelable</title><content type='html'>Your Android application needs to pass some custom data between processes in an Intent.  You will be calling Intent.putExtra(String, &lt;a href="http://code.google.com/android/reference/android/os/Parcelable.html"&gt;Parcelable&lt;/a&gt;).  It would be easier to test if the Parcel class where not final with only private constructors.  That keeps us from testing the methods individually.  We are forced to perform only round trip testing -- write our Parcelable to a Parcel, then call the creator with the same Parcel instance.&lt;br /&gt;&lt;br /&gt;There is one important step right in the middle of the round trip.  The Parcel needs to be reset to be ready for read.  Think of this just like working with java.nio.ByteBuffer.  With ByteBuffer, when you are done writing, you call flip.  With Parcel, when you want to read -- call setDataPosition(0).  Here is a sample test.&lt;br /&gt;&lt;br /&gt;I'll decoreate a Person object as a ParcelablePerson that implements the Parcelable interface and has the requisite public static final CREATOR.  Following TDD I've only created enough of the implementation code below to make the test compile.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;    public void testPersonTakesRoundTripThroughParcel() throws Exception {&lt;br /&gt;        Person testPerson = new Person();&lt;br /&gt;        ParcelablePerson testObject = new ParcelablePerson(testPerson);&lt;br /&gt;        Parcel parcel = Parcel.obtain();&lt;br /&gt;        testObject.writeToParcel(parcel, 0);&lt;br /&gt;        //done writing, now reset parcel for reading&lt;br /&gt;        parcel.setDataPosition(0);&lt;br /&gt;        //finish round trip&lt;br /&gt;        ParcelablePerson createFromParcel = ParcelablePerson.CREATOR.createFromParcel(parcel);&lt;br /&gt;       &lt;br /&gt;        assertEquals(testPerson, createFromParcel.getPerson());&lt;br /&gt;    }&lt;br /&gt;    public class Person {&lt;br /&gt;       ...&lt;br /&gt;    }&lt;br /&gt;    public class ParcelablePerson implements Parcelable {&lt;br /&gt;        private Person person;&lt;br /&gt;        public ParcelablePerson(Person person) {&lt;br /&gt;            this.person = person;&lt;br /&gt;        }&lt;br /&gt;       &lt;br /&gt;        public Person getPerson() {&lt;br /&gt;            return person;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        public int describeContents() {&lt;br /&gt;            return 0;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        public void writeToParcel(Parcel dest, int flags) {&lt;br /&gt;            //call dest.write... methods&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static final Creator&lt;parcelableperson&gt; CREATOR = new Creator&lt;parcelableperson&gt;() {&lt;br /&gt;            @Override&lt;br /&gt;            public ParcelablePerson createFromParcel(Parcel source) {&lt;br /&gt;                return null;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            @Override&lt;br /&gt;            public ParcelablePerson[] newArray(int size) {&lt;br /&gt;                return null;&lt;br /&gt;            }};&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-3348278742500339382?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/3348278742500339382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=3348278742500339382' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/3348278742500339382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/3348278742500339382'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/02/unit-test-your-custom-parcelable.html' title='Unit Test Your Custom Parcelable'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-1091529524269242061</id><published>2009-01-29T22:14:00.008-06:00</published><updated>2009-01-31T08:34:18.411-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Android View XML</title><content type='html'>I am thoroughly enjoying using XML to define the view characteristics of my Android application.  I've written GUI code in Visual Basic, Swing, RCP, and a dab of GTK+.  None of them are as easy and elegant as using XML.  I applaud the Android team in using this approach.&lt;br /&gt;&lt;br /&gt;Don't forget to apply some style to your view.  Who would want to look at some boring, white standard font.  Checkout the  Android documentation on &lt;a href="http://code.google.com/android/reference/available-resources.html#stylesandthemes"&gt;styles and themes&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;But don't stop at using only the view components that Android supplies.  Good object oriented design encompasses creating custom view components for your custom data objects.  If you have a domain object called Person that needs to be displayed then you should have a custom composite view that knows exactly how a Person is displayed -- err, the attributes of the person are displayed.  I learned over &lt;a href="http://mylifewithandroid.blogspot.com/2008/04/custom-views.html"&gt;here&lt;/a&gt; that using custom view controls in the XML is as easy as defining an xml element with the name of your custom view.&lt;br /&gt;&lt;br /&gt;I put together the below example as a guide.  It is not meant to be an exemplar.  Note that i have a LinearLayout that defines padding.  That likely belongs in a style instead of being defined solely for THAT LinearLayout.  With that warning in place, here's an exmple of a my.app.PersonComposite which is a custom class that extends LinearLayout.  To use this custom view component in your XML then you would include something like the following:&lt;br /&gt;&lt;blockquote&gt;&amp;lt;my.app.PersonComposite&lt;br /&gt;   android:id="@+id/person"&lt;br /&gt;   android:layout_width="fill_parent"&lt;br /&gt;   android:layout_height="wrap_content"&lt;br /&gt;/&gt;&lt;br /&gt;&lt;/blockquote&gt;So, that element will put a PersonComposite in your activity.  But what does the PersonComposite look like?  Well, that should be defined in xml as well.  In the constructors of PersonComposite, include the following:&lt;br /&gt;       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);&lt;br /&gt;       View inflatedView = inflater.inflate(R.layout.person_composite, this);&lt;br /&gt;&lt;br /&gt;In order for this to work, you'll need to have a ./res/layout/person_composite.xml.  Perhaps something like this:&lt;br /&gt;&lt;blockquote&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;   android:orientation="horizontal"&lt;br /&gt;   android:padding="2dp"&lt;br /&gt;   android:layout_width="wrap_content"&lt;br /&gt;   android:layout_height="wrap_content"&lt;br /&gt;   &gt;&lt;br /&gt;       &amp;lt;TextView&lt;br /&gt;           style="@style/BigAndBlue"&lt;br /&gt;           android:id="@+id/personLastName"&lt;br /&gt;           android:layout_width="wrap_content"&lt;br /&gt;           android:layout_height="wrap_content"&lt;br /&gt;           android:text="@string/not_given_default"&lt;br /&gt;           /&gt;&lt;br /&gt;     &lt;br /&gt;       &amp;lt;TextView&lt;br /&gt;           android:id="@+id/personFirstName"&lt;br /&gt;           android:layout_width="wrap_content"&lt;br /&gt;           android:layout_height="wrap_content"&lt;br /&gt;           android:text="@string/not_given_default"&lt;br /&gt;       /&gt;&lt;br /&gt;&amp;lt;/LinearLayout&gt;&lt;/blockquote&gt;Note that the style attribute conspicuously lacks the android namespace. Hmm?  Oh well, just watch out for that.  We have to define that Style over in ./res/values/styles.xml:&lt;br /&gt;&lt;blockquote&gt;&amp;lt;resources&gt;&lt;br /&gt; &amp;lt;style name="BigAndBlue"&gt;&lt;br /&gt;   &amp;lt;item name="android:textSize"&gt;12pt&amp;lt;/item&gt;&lt;br /&gt;   &amp;lt;item name="android:textColor"&gt;#008&amp;lt;/item&gt;&lt;br /&gt;&amp;lt;/style&gt;&lt;br /&gt;&amp;lt;/resources&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-1091529524269242061?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/1091529524269242061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=1091529524269242061' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/1091529524269242061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/1091529524269242061'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/01/android-view-xml.html' title='Android View XML'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-6041954831415101745</id><published>2009-01-13T22:39:00.007-06:00</published><updated>2009-01-13T23:18:20.807-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Unit Testing Android Applications</title><content type='html'>Unit testing my Android application has put strain on my patience.  All of my unit tests are not just one quick key stroke.  I already posted regarding mock testing an Android project.  Integration tests are another issue.  These tests have to run inside the container -- the emulator or phone.  I got started writing integration tests by reading &lt;a href="http://docs.google.com/View?docid=ddwc44gs_49stmqs7hb"&gt;this document&lt;/a&gt;.  You'll find more Android topics discussed at &lt;a href="http://dtmilano.blogspot.com/"&gt;his blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I followed Diego's steps to setup the test-specific eclipse project.  Then I created an external tool configuration to launch the tests:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_LX0ty8ZcDsc/SW1yVBx-YqI/AAAAAAAAAAo/s5weXwcKiGk/s1600-h/Screenshot-External+Tools+Configurations+.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 201px;" src="http://2.bp.blogspot.com/_LX0ty8ZcDsc/SW1yVBx-YqI/AAAAAAAAAAo/s5weXwcKiGk/s320/Screenshot-External+Tools+Configurations+.png" alt="" id="BLOGGER_PHOTO_ID_5291010842811064994" border="0" /&gt;&lt;/a&gt;The "Functional Tests" run configuration changes the arguments to:&lt;br /&gt;&lt;blockquote&gt;shell  am instrument -w -e func true com.wilson.android.libary.test/android.test.InstrumentationTestRunner&lt;br /&gt;&lt;/blockquote&gt;Now each time I'm ready to run the tests I need to deploy the main project, the test project -- if they both changed.  Now I can use one of the run configurations above to use "adb" to launch the tests.&lt;br /&gt;&lt;br /&gt;Be sure to read the official documentation on running instrumentation tests, starting &lt;a href="http://code.google.com/android/reference/android/test/InstrumentationTestRunner.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-6041954831415101745?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/6041954831415101745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=6041954831415101745' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6041954831415101745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6041954831415101745'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2009/01/unit-testing-android-applications.html' title='Unit Testing Android Applications'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SW1yVBx-YqI/AAAAAAAAAAo/s5weXwcKiGk/s72-c/Screenshot-External+Tools+Configurations+.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-6852894418919451976</id><published>2008-12-23T06:47:00.003-06:00</published><updated>2008-12-23T07:12:59.967-06:00</updated><title type='text'>Android: The New Container</title><content type='html'>In the early days of Java &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Servlet&lt;/span&gt; development back in 1996 we had very little tool support.  As the tools evolved the teams I was a part of started incorporating multiple build paths.  The code was built in the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;IDE&lt;/span&gt;, but it was also built on the desktop using &lt;a href="http://ant.apache.org"&gt;ant&lt;/a&gt;.  This was good because the developers were building the same way as &lt;a href="http://cruisecontrol.sourceforge.net/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;Cruisecontrol&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I think Android is going to be no different.  I see a strong correlation between writing and testing &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;servlets&lt;/span&gt; to run in the J2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;EE&lt;/span&gt; container and writing GUI and services for Android.  For me this is marking a return to a platform with week tool support.  The weakness I'm first percieving is unit testing.  I have not yet found how to press one button to run all the tests.  That is, one button press will launch the emulator (if needed), hot deploy the code to the container/emulator, and execute the in-container tests.  Then there is the out-of-container tests that have no dependency upon the container.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-6852894418919451976?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/6852894418919451976/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=6852894418919451976' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6852894418919451976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6852894418919451976'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2008/12/android-new-container.html' title='Android: The New Container'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-8495173378341291073</id><published>2008-12-22T09:59:00.003-06:00</published><updated>2008-12-22T10:28:05.087-06:00</updated><title type='text'>Google Docs Publish to Blog Feature</title><content type='html'>My Android &amp;amp; Mockito post came from Google docs - publish to blog - feature.  I had much higher expectations that the formatting wouldn't get mangled.  My code segments lost their indent!  I must have missed some requirement.  Just my style to initially think I've done something wrong or the problem would have been fixed by now.  I'll think that way until I prove myself wrong, and so doing prove myself right -- that I used the feature right.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-8495173378341291073?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/8495173378341291073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=8495173378341291073' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/8495173378341291073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/8495173378341291073'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2008/12/my-android-mockito-post-came-from.html' title='Google Docs Publish to Blog Feature'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-7942502271072596484</id><published>2008-12-22T09:49:00.002-06:00</published><updated>2008-12-22T09:53:57.231-06:00</updated><title type='text'>Android &amp; Mockito</title><content type='html'>During the day I'm a mild mannered (debatable) Java developer currently paid to  work on a multi-threaded server with it's own RCP client.  This is important because I've started to pick up some habits from that team.  One habit in particular is the importance of using a mocking framework.  The day job uses jMock.  I find the expectations blocks clumsy things that run against the flow of a non-mocking JUnit test.  As a result I've started using Mockito on my own projects.  I try to avoid theological debates out this framework or that.  It's more important that I like the public interface.  It doesn't decrease the value of a mocking (or stubing) framework.&lt;br /&gt;&lt;br /&gt;My wife recently encouraged me to buy an HTC G1 phone.  She's great, isn't she!  Two days later, I'm using the development kit, working on my first application.  After poking around at the API, and getting the lay of the land it was time to get serious and understand how to interact with the platform.  To that end I need to write some unit tests.&lt;br /&gt;&lt;br /&gt;So I want to write a unit test for an implementation of android.view.View.OnClickListener.  The interface has only one method, no surprise here, it's an onClick method: "public void onClick(View view)".   Here's my implementation:&lt;br /&gt;&lt;blockquote&gt;class MyOnclickListener implements OnClickListener {&lt;br /&gt;    public void onClick(View view) {&lt;br /&gt;        Intent intent = new Intent("a.unique.string");&lt;br /&gt;        intent.addCategory(Intent.CATEGORY_DEFAULT);&lt;br /&gt;        activity.startActivityForResult(intent, 1);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;What the "activity.startActivityForResult" method does is not germane to this story.  Just know that I need a test that makes sure that method is called with the right Intent.  How do I know it's the right Intent object?  So here's my first pass at a test:&lt;br /&gt;&lt;blockquote&gt;    @Test&lt;br /&gt;    public void onClick_WithRealIntent() throws Exception {&lt;br /&gt;        Activity mockActivity = Mockito.mock(Activity.class);&lt;br /&gt;        View mockView = Mockito.mock(View.class);&lt;br /&gt;&lt;br /&gt;        MyOnclickListener testObject = new MyOnclickListener(mockActivity);&lt;br /&gt;        testObject.onClick(mockView);&lt;br /&gt;       &lt;br /&gt;        Intent expectedIntent = new Intent("com.google.zxing.client.android.SCAN");&lt;br /&gt;        Mockito.verify(mockActivity).startActivityForResult(expectedIntent, 1);&lt;br /&gt;    }&lt;br /&gt;&lt;/blockquote&gt;I'm betting here that the Intent object has an equals method based on that constructor argument.  But running this test fails horribly.  Now, I should note that in RCP fashion I've created a separate project to hold my unit tests.  So the test project (in Eclipse) depends on the "real" project.  Both projects have the android buildSpec and nature.&lt;br /&gt;&lt;blockquote&gt;#&lt;br /&gt;# An unexpected error has been detected by Java Runtime Environment:&lt;br /&gt;#&lt;br /&gt;#  Internal Error (434C41535326494C453041525345520E4350500B65), pid=14086, tid=3084753808&lt;br /&gt;#&lt;br /&gt;# Java VM: Java HotSpot(TM) Server VM (1.6.0_03-b05 mixed mode)&lt;br /&gt;# An error report file with more information is saved as hs_err_pid14086.log&lt;br /&gt;#&lt;br /&gt;# If you would like to submit a bug report, please visit:&lt;br /&gt;#   http://java.sun.com/webapps/bugreport/crash.jsp&lt;br /&gt;#&lt;br /&gt;&lt;/blockquote&gt;So I poke around after the crash file reveals little to no details of what happened.  And low, and behold, there is evidence that &lt;a title="android junit run configurations fails by default" href="http://code.google.com/android/kb/troubleshooting.html#addjunit" id="u.1x"&gt;android junit run configurations fail by default&lt;/a&gt;.  So we have to edit the run configuration as suggested and try again.  I'll point out that I'm not exactly as they suggest.  I'm using Junit4, my bootstrap classpath is only the JRE library, and I added android.jar to the UserEntries under the default classpath.&lt;br /&gt;&lt;blockquote&gt;java.lang.RuntimeException: Stub!&lt;br /&gt;    at android.content.Intent.&amp;lt;init&amp;gt;(Intent.java:27)&lt;br /&gt;    ...&lt;br /&gt;&lt;/blockquote&gt;Argh!  What's that mean!  We could take a look at the android source code to see what happens on Intent.java:27.  Our implementation class will still have to call "Intent intent = new Intent("a.unique.string");".  Now comes in another habit picked up from the day job.  I'm still not sure if this habit is a good one.  When dealing with the JMock tests for the projects server there is a series of "provider" classes.  These are really simple factory pattern classes that don't have any logic, they just new up an object, they they provide instead of factor(y).  Here's what I mean:&lt;br /&gt;&lt;blockquote&gt;public class MyOnclickListener implements OnClickListener {&lt;br /&gt;    private final Activity activity;&lt;br /&gt;    private final IntentProvider intentProvider;&lt;br /&gt;&lt;br /&gt;    public MyOnclickListener(Activity activity) {&lt;br /&gt;        this(activity, new IntentProvider());&lt;br /&gt;    }&lt;br /&gt;   &lt;br /&gt;    MyOnclickListener(Activity activity, IntentProvider intentProvider) {&lt;br /&gt;        this.activity = activity;&lt;br /&gt;        this.intentProvider = intentProvider;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void onClick(View view) {&lt;br /&gt;        Intent intent = intentProvider.provideIntent();&lt;br /&gt;       &lt;br /&gt;        activity.startActivityForResult(intent, 1);&lt;br /&gt;    }&lt;br /&gt;   &lt;br /&gt;    static class IntentProvider {&lt;br /&gt;        public Intent provideIntent() {&lt;br /&gt;            Intent intent = new Intent("a.unique.string");&lt;br /&gt;            intent.addCategory(Intent.CATEGORY_DEFAULT);&lt;br /&gt;            return intent;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/blockquote&gt;That package visible constructor is for our test.  Now our test can use a mock Intent because the test is going to provide a mock IntentProvider:&lt;br /&gt;&lt;blockquote&gt;    @Test&lt;br /&gt;    public void onClick_startsActivity_WithTheRightIntent() throws Exception {&lt;br /&gt;        Activity mockActivity = Mockito.mock(Activity.class);&lt;br /&gt;        Intent mockIntent = Mockito.mock(Intent.class);&lt;br /&gt;       &lt;br /&gt;        Mockito.when(mockIntentProvider.provideIntent()).thenReturn(mockIntent);&lt;br /&gt;       &lt;br /&gt;        MyOnclickListener testObject = new MyOnclickListener(mockActivity, mockIntentProvider);&lt;br /&gt;        View mockView = Mockito.mock(View.class);&lt;br /&gt;        testObject.onClick(mockView);&lt;br /&gt;       &lt;br /&gt;        Mockito.verify(mockActivity).startActivityForResult(mockIntent, 1);&lt;br /&gt;    }&lt;br /&gt;&lt;/blockquote&gt;and now we have a green bar.  But at what cost?  This is an important question.  We just created a constructor and an inner class JUST FOR THE TEST.   Those two elements doubled the amount of code in MyOnClickListener!  This is not the end.  I'll contiue to analyze this issue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-7942502271072596484?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/7942502271072596484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=7942502271072596484' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7942502271072596484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7942502271072596484'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2008/12/android-mockito.html' title='Android &amp;amp; Mockito'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-5038476809225166202</id><published>2008-11-12T07:35:00.003-06:00</published><updated>2008-11-12T07:52:49.169-06:00</updated><title type='text'>ThinkPad Dual Screen</title><content type='html'>I needed to use the VGA output on my Thinkpad to give a demonstration on Java Connector Architecture.  A very short search later led me to this forum posting &lt;a href="http://ubuntuforums.org/showthread.php?t=346555"&gt;http://ubuntuforums.org/showthread.php?t=346555&lt;/a&gt; that has a link to this &lt;a href="http://ozlabs.org/%7Ejk/docs/mergefb/"&gt;http://ozlabs.org/~jk/docs/mergefb/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now I can use xrandr to turn on and off rudimentary screen mirror.&lt;br /&gt;&lt;blockquote&gt;xrandr --output VGA --auto&lt;br /&gt;xrandr --output VGA --off&lt;/blockquote&gt;&lt;br /&gt;I'll update here when I successfully get the desktop spread across both screens.  As a word of warning, I just turned of xrandr VGA output (--off) and all running applications were locked.  I could swap focus between them but the applications themselves did not respond.  Beware.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-5038476809225166202?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/5038476809225166202/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=5038476809225166202' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/5038476809225166202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/5038476809225166202'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2008/11/thinkpad-dual-screen.html' title='ThinkPad Dual Screen'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-2847810768428167102</id><published>2008-10-22T15:34:00.003-05:00</published><updated>2008-10-22T15:40:22.985-05:00</updated><title type='text'>When Did I Start Work Today (linux)</title><content type='html'>When working in Windows (XP at least) it's an easy matter to jump to the event viewer security log to see when you first authenticated this morning.  Here's a handy way to get the same information from Linux.  Just replace the [your.user.name.here] with the name with which you authenticate.&lt;br /&gt;&lt;blockquote&gt;  su -&lt;br /&gt;   grep pam.*[your.user.name.here] /var/log/messages &lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-2847810768428167102?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/2847810768428167102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=2847810768428167102' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2847810768428167102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/2847810768428167102'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2008/10/when-did-i-start-work-today-linux.html' title='When Did I Start Work Today (linux)'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-7382107833017677014</id><published>2008-09-26T08:11:00.002-05:00</published><updated>2008-09-26T08:21:36.500-05:00</updated><title type='text'>Pretty Print XML in Java</title><content type='html'>Something I keep forgetting how to do.  Obviously something would need to be done to make this any sort of utility class.  This is simply an example of the classes that can be used to perform pretty print of an xml string.  There are many more ways to get the actual string from a file or Document.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;import java.io.ByteArrayInputStream;&lt;br /&gt;import java.io.InputStream;&lt;br /&gt;import java.io.OutputStream;&lt;br /&gt;&lt;br /&gt;import javax.xml.parsers.DocumentBuilder;&lt;br /&gt;import javax.xml.parsers.DocumentBuilderFactory;&lt;br /&gt;import javax.xml.transform.OutputKeys;&lt;br /&gt;import javax.xml.transform.Transformer;&lt;br /&gt;import javax.xml.transform.TransformerException;&lt;br /&gt;import javax.xml.transform.TransformerFactory;&lt;br /&gt;import javax.xml.transform.dom.DOMSource;&lt;br /&gt;import javax.xml.transform.stream.StreamResult;&lt;br /&gt;&lt;br /&gt;import org.w3c.dom.Document;&lt;br /&gt;&lt;br /&gt;public class XmlTest {&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) throws Exception {&lt;br /&gt;  String xmlString = "&amp;lt;tag&gt;&amp;lt;nested&gt;hello&amp;lt;/nested&gt;&amp;lt;/tag&gt;";&lt;br /&gt;  DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();&lt;br /&gt;&lt;br /&gt;  InputStream inputStream = new ByteArrayInputStream(xmlString.getBytes());&lt;br /&gt;  Document document = documentBuilder.parse(inputStream);&lt;br /&gt;&lt;br /&gt;  XmlTest xmlTest = new XmlTest();&lt;br /&gt;  xmlTest.serialize(document, System.out);&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void serialize(Document doc, OutputStream out) throws Exception {&lt;br /&gt;&lt;br /&gt;  TransformerFactory tfactory = TransformerFactory.newInstance();&lt;br /&gt;  Transformer serializer;&lt;br /&gt;  try {&lt;br /&gt;   serializer = tfactory.newTransformer();&lt;br /&gt;   //Setup indenting to "pretty print"&lt;br /&gt;   serializer.setOutputProperty(OutputKeys.INDENT, "yes");&lt;br /&gt;   serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");&lt;br /&gt;&lt;br /&gt;   DOMSource xmlSource = new DOMSource(doc);&lt;br /&gt;   StreamResult outputTarget = new StreamResult(out);&lt;br /&gt;   serializer.transform(xmlSource, outputTarget);&lt;br /&gt;  } catch (TransformerException e) {&lt;br /&gt;   // this is fatal, just dump the stack and throw a runtime exception&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;&lt;br /&gt;   throw new RuntimeException(e);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-7382107833017677014?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/7382107833017677014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=7382107833017677014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7382107833017677014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/7382107833017677014'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2008/09/pretty-print-xml-in-java.html' title='Pretty Print XML in Java'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-6415267503959882734</id><published>2008-09-22T07:50:00.005-05:00</published><updated>2008-10-16T08:11:53.783-05:00</updated><title type='text'></title><content type='html'>I drafted this description of services to give non-technical individuals understanding of the services of a Service Oriented Architecture (SOA).  I refined it a smidge here from its original context.  It is not a complete, thorough example.  It focuses on giving a definition to the word &lt;span style="font-weight:bold;"&gt;service&lt;/span&gt;.&lt;br /&gt;&lt;blockquote&gt;We use services everyday.  An example is that you don't have to be a barista to drink an espresso.  You simply order, pay, and enjoy your beverage.  This analogy has a good correlation with the service orientation of software architecture.  In software we call this a black box.  You don't know what happens inside the box.  You put in money and espresso comes out.  A service consumer needs no knowledge of how a provider has implemented a service.  The Consumer need only know the input required and output expected from the service.  In our example of the espresso service, a barista takes money as input and outputs espresso.  As a consumer, I need not know how to grow, harvest, roast, and brew coffee beans.&lt;br /&gt;&lt;br /&gt;There are cost and quality aspects to consider.  How much will it cost the service consumer, who has no prior knowledge of coffee beans, to go from plant to espresso?  Would the quality be the same as when the coffee experts do the same thing?  Clearly the answer is to leave espresso and the service logic to the experts.  This frees each consumer to put full effort into their own area of expertise. &lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-6415267503959882734?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/6415267503959882734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=6415267503959882734' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6415267503959882734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/6415267503959882734'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2008/09/i-drafted-this-description-of-services.html' title=''/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1776345669994681097.post-45806535603520320</id><published>2008-09-16T15:47:00.000-05:00</published><updated>2008-09-16T15:56:19.064-05:00</updated><title type='text'>Welcome and Thank You</title><content type='html'>There is such a wealth of information on the internet.  I am continually amazed.  I have such an expectation that someone else already gave a good answer for any question, that I won't need to provide answers of my own.  I do however need a space where I can catalog the answers I have found.  Who knows, maybe I'll eventually find a topic that I can provide a novel approach to solving.  Should it happen I can use this space to share and give back to the community from which I have gained so much.&lt;br /&gt;&lt;br /&gt;So I say welcome to my blog.  I also say thank you.  Thank you, internet, for all the answers past, present, and future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1776345669994681097-45806535603520320?l=stuffikeepforgettinghowtodo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffikeepforgettinghowtodo.blogspot.com/feeds/45806535603520320/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1776345669994681097&amp;postID=45806535603520320' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/45806535603520320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1776345669994681097/posts/default/45806535603520320'/><link rel='alternate' type='text/html' href='http://stuffikeepforgettinghowtodo.blogspot.com/2008/09/welcome-and-thank-you.html' title='Welcome and Thank You'/><author><name>James Wilson</name><uri>http://www.blogger.com/profile/06723635153103504657</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/_LX0ty8ZcDsc/SVrcNknXBMI/AAAAAAAAAAM/seTxih4V86A/S220/wilson-james2-head.jpg'/></author><thr:total>0</thr:total></entry></feed>
