<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:thr='http://purl.org/syndication/thread/1.0' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-1973750947775262558</atom:id><lastBuildDate>Mon, 30 Aug 2010 10:19:03 +0000</lastBuildDate><title>MXUnit Blog</title><description></description><link>http://blog.mxunit.org/</link><managingEditor>noreply@blogger.com (bill shelton)</managingEditor><generator>Blogger</generator><openSearch:totalResults>171</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-8051338759033994087</guid><pubDate>Thu, 26 Aug 2010 22:28:00 +0000</pubDate><atom:updated>2010-08-26T18:28:26.427-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>MongoDB</category><category domain='http://www.blogger.com/atom/ns#'>conferences</category><title>MongoDB at Ria Unleashed</title><description>&lt;p&gt;&lt;a href="http://riaunleashed.com/" target="_blank"&gt;RIA Unleashed&lt;/a&gt; is back for a 2nd year, and it’s going to be a great one? Why? Because yours truly is speaking, naturally!&lt;/p&gt;  &lt;p&gt;No no no, I’m not going to yap for yet another hour on unit test this, TDD that, automate blah blah blah. This time, MongoDB gets some lovin’. &lt;/p&gt;  &lt;p&gt;See, a while back, Billy started poking about with Mongo. He wrote &lt;a href="http://blog.mxunit.org/search/label/MongoDB" target="_blank"&gt;some blog posts&lt;/a&gt; and started &lt;a href="http://github.com/marcesher/cfmongodb" target="_blank"&gt;CFMongoDB&lt;/a&gt;. As fate would have it, earlier this year I had a chance to work on a project using Mongo, and I took to it quite naturally. With Billy going back to school to join the neckbeards doing Ph.D. work, I’ve taken up the reigns of CFMongoDB for the timebeing. Meanwhile, Brian Rinaldi asked me if I’d like to speak at RIA Unleashed, and he graciously accepted a topic on Mongo. Here it is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;MongoDB is a popular open source Document-oriented database. Like other NoSQL datastores, it's fast and scalable. Unlike most others, it provides rich ad-hoc query capabilities which we ColdFusion developers know and love. During the presentation, I'll give a broad overview of the usual introductory topics: MongoDB's &amp;quot;solution space&amp;quot;, installation, working with the shell, administration, and replication. Then I'll dive into using Mongo with ColdFusion, showing why I enjoy working with Mongo, the problems I've encountered, and how to solve them.      &lt;br /&gt;By session's end, attendees should understand what problems MongoDB was meant to address and how to use MongoDB as a datastore in their CFML projects.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;RIA Unleashed is a kick-ass, reasonably priced, 2-day conference featuring both &lt;a href="http://riaunleashed.com/page.cfm/topics" target="_blank"&gt;sessions&lt;/a&gt; and &lt;a href="http://riaunleashed.com/page.cfm/workshops" target="_blank"&gt;workshops&lt;/a&gt; by world-famous speakers such as Ray Camden, Jesse Warden, Bob “All Your Mocks Are Belong to Us” Silverberg, and the guy who created &lt;a href="http://riaunleashed.com/page.cfm/speakers/charles-schulze" target="_blank"&gt;Peanuts&lt;/a&gt;! &lt;/p&gt;  &lt;p&gt;During its inaugural year, teh twitterz were buzzing with compliments. This year will be even better!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-8051338759033994087?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/08/mongodb-at-ria-unleashed.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-91590053806630123</guid><pubDate>Sat, 17 Jul 2010 23:36:00 +0000</pubDate><atom:updated>2010-07-18T09:49:08.524-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>coldfusion</category><category domain='http://www.blogger.com/atom/ns#'>SQL Server</category><category domain='http://www.blogger.com/atom/ns#'>ORM</category><title>CF9 ORM: Using the Secondary Cache to optimize for expensive columns</title><description>&lt;p&gt;This is an experiment. It most likely speaks to my poor SQL skills and willingness to jump for a quicker code solution than to figure out how to write faster queries. So if you can tell me a faster way to do this in SQL, I’ll listen. &lt;/p&gt;  &lt;p&gt;Still, this is mostly about using a combination of simple property mappings and the secondary cache for an interesting, perhaps unusual solution to a problem.&lt;/p&gt;  &lt;h2&gt;This is my story&lt;/h2&gt;  &lt;p&gt;I have a table. Its name is “N_Organizations”. It’s prefixed with “N_” because this is a blog post and I am experimenting. Like many organizations, an Org can be a parent of another Org: “Paint Shop” is a child of “Operations” is a child of “The Penthouse Suite”. In an untold number of places, in both the web application and in reports that are not web-driven, the “tree” for any given child organization has a simple requirement: Show the names of the parents as a single string:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;The Penthouse Suite –&amp;gt; Operations –&amp;gt; Paint Shop”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Ideally, The creation of this string would happen in one place, and then any place that needed it would not have to do the requisite looping to construct the string itself. If different formatting were needed, it’d be better to have the reformatter be a simple string reformatter than a parent org climber: simply replace the arrows with colons, for example.&lt;/p&gt;  &lt;p&gt;So, when thinking of a typical query, you’d get something like this:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;pre&gt;id | Name                  | ParentID | ParentName
1    The Penthouse Suite     null       
2    Operations              1          The Penthouse Suite
3    Paint Shop              2          The Penthouse Suite --&amp;gt; Operations&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;And so on.&lt;/p&gt;

&lt;p&gt;To fetch this stuff, I created a view that uses a Common Table Expression (CTE) to recursively loop over the parents in order to derive the ParentName. It does some other foolishness with “level”, but ignore that. CTEs are kind of like recursing but without functions:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;CREATE view [dbo].[v_organizations]   as

WITH cte_tree AS
		(
			SELECT id, organizationname, OrgNode.GetLevel() as Level, CAST('' AS varchar(500)) AS ParentName
			FROM dbo.n_organizations
			WHERE organizationtypecode = 'D'

			UNION all

			SELECT parent.id, parent.organizationname, OrgNode.GetLevel() as Level,
			CAST(
				cte_tree.parentName +
				case when cte_tree.parentname = '' then '' else ': ' end
				+  cte_tree.organizationname as varchar(500)
			)
			FROM dbo.n_organizations parent
			JOIN cte_tree ON parent.parentorganizationid = cte_tree.id
		)
		SELECT
			o.id, o.OrganizationName, OrganizationTypeCode,
				ParentOrganizationID, CreatedOn, ModifiedOn, 
				Level,
				case when Level &amp;lt;=3 then o.id else o.ParentOrganizationID end as GroupLevel,
			cte_tree.ParentName
		FROM cte_tree
		JOIN dbo.n_organizations o ON cte_tree.id = o.id

GO&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;There’s a big problem with this: it’s slow. The tables are as indexed as they can be, but you can’t index views with CTEs. And what’s worse, the query is slow regardless of what kind of criteria you add to it.&amp;#160; &lt;/p&gt;

&lt;p&gt;Select * from v_Organizations runs about 125 milliseconds. Select * from v_Organizations where id = 215 runs in about 90 ms. The reason is that it still has to do all that recursion. &lt;strong&gt;Thus, this is probably a terrible way to solve this problem.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And yet, we continue….&lt;/p&gt;

&lt;h2&gt;This is my Component&lt;/h2&gt;

&lt;p&gt;Organization.cfc&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;component persistent=&amp;quot;true&amp;quot; accessors=&amp;quot;true&amp;quot; table=&amp;quot;N_Organizations&amp;quot; {
	property name=&amp;quot;id&amp;quot; fieldtype=&amp;quot;id&amp;quot; generator=&amp;quot;native&amp;quot;;
	property name=&amp;quot;organizationName&amp;quot; type=&amp;quot;string&amp;quot;;
	property name=&amp;quot;parentName&amp;quot; column=&amp;quot;parentName&amp;quot; readonly=&amp;quot;true&amp;quot; type=&amp;quot;string&amp;quot;  table=&amp;quot;v_organizations&amp;quot; joincolumn=&amp;quot;id&amp;quot; cacheuse=&amp;quot;read-only&amp;quot;;
}&lt;/pre&gt;

&lt;p&gt;Notice how the parentName property points to “v_organizations” as the table? Pretty cool, huh?&amp;#160; So now when I load this component, when I access the parentName property, it’ll pull it from v_organizations and all will be well. Hibernate will generate a query that simply joins table N_Organizations on v_Organizations where id = id. Yeah.&lt;/p&gt;

&lt;p&gt;Except, that’s slow, too. Remember, as I said, querying v_organizations adds about 100ms no matter how many records I’m pulling back. Notice that “cacheuse=’read-only” attribute? Yeah… that doesn’t work. No matter how many times I ask for the parentName, it’s going to run that same query.&lt;/p&gt;

&lt;h2&gt;What If?&lt;/h2&gt;

&lt;p&gt;What if I just cached the Organization.cfc in Secondary cache? Wouldn’t that rock? No… most of the data in this component will change too frequently, so I can’t cache the entire component (I’m leaving off a bunch of other properties, obviously). &lt;/p&gt;

&lt;p&gt;But… what if I could cache just that parentName property? That’s the slow one, after all. And that never changes. Or, it changes like 2x a year, and in that case, we just clear the cache and off we go.&lt;/p&gt;

&lt;h2&gt;How could you possibly achieve such awesomeness?&lt;/h2&gt;

&lt;p&gt;You need two components: 1) Your original Organization.cfc and 2) a new ParentName.cfc&lt;/p&gt;

&lt;p&gt;Organization.cfc:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;component persistent=&amp;quot;true&amp;quot; accessors=&amp;quot;true&amp;quot; table=&amp;quot;N_Organizations&amp;quot;{
	property name=&amp;quot;id&amp;quot; fieldtype=&amp;quot;id&amp;quot; generator=&amp;quot;native&amp;quot;;
	property name=&amp;quot;organizationName&amp;quot; type=&amp;quot;string&amp;quot;;
	property name=&amp;quot;parentName&amp;quot; readonly=&amp;quot;true&amp;quot; type=&amp;quot;string&amp;quot; fieldtype=&amp;quot;one-to-one&amp;quot; cfc=&amp;quot;ParentName&amp;quot; constrained=&amp;quot;true&amp;quot; cacheuse=&amp;quot;read-only&amp;quot; ;
	
	//make it easy to get the parentName property
	function getParentName(){
		try { return parentName.getParentName(); }
        	catch(Any e) { return &amp;quot;&amp;quot;; }
	}

}&lt;/pre&gt;

&lt;p&gt;ParentName.cfc&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;component accessors=&amp;quot;true&amp;quot; persistent=&amp;quot;true&amp;quot; readonly=&amp;quot;true&amp;quot; table=&amp;quot;v_Organizations&amp;quot; cacheuse=&amp;quot;read-only&amp;quot; cachename=&amp;quot;ParentName&amp;quot;{
	property name=&amp;quot;id&amp;quot; fieldtype=&amp;quot;id&amp;quot;;
	property name=&amp;quot;parentName&amp;quot; type=&amp;quot;string&amp;quot; ;
}&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;So what does this do, exactly?&lt;/h3&gt;

&lt;p&gt;First, what we’ve done is simply rolled that parentName field from v_organizations into a 4-line component. Notice that the “table” attribute on the component is v_organizations. Notice it specifies cacheuse=”read-only”. Notice that read-only is true. &lt;/p&gt;

&lt;p&gt;Second, in Organization.cfc, we replaced the original parentName property with a new one that is a simple one-to-one relationship with this new ParentName property&lt;/p&gt;

&lt;p&gt;Third,we add a function, getParentName(),&amp;#160; so that we could simply call organization.getParentName() instead of organization.getParentName().getParentName(). It’s wrapped in try/catch because this will fail for the very top-level organization which has no parent organization. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result: &lt;/strong&gt;The first time getParentName() is called for any organization, the view will run (slowly, as usual). Subsequently, CF will fetch that property from the cache until that cache is cleared or the server restarts or whatever. So you do take an initial one-time hit of 90ms or so for each organization, but after that, you’re gold.&lt;/p&gt;

&lt;h2&gt;&lt;/h2&gt;

&lt;h2&gt;But wait, there’s more!&lt;/h2&gt;

&lt;p&gt;I mentioned this experiment to &lt;a href="http://www.firemoss.com" target="_blank"&gt;my boss&lt;/a&gt;, and his first reaction was, Could you just do a one-time load of all those ParentName organization instances, right on app start, so that you’d never see that 90-ms / per object penalty?&lt;/p&gt;

&lt;p&gt;So I tried it, and this is where it gets even better. None of this is unsurprising, by the way. It all makes complete sense.&lt;/p&gt;

&lt;p&gt;Simple math:&lt;/p&gt;

&lt;p&gt;Doing it the ‘pay-as-you-go’ way: You have 2500 records. You hit the view one time for each record. 2500 * 90ms = 225000 ms = 225 seconds = almost 4 minutes total to load each of those records &lt;strong&gt;&lt;em&gt;were you to do them one at a time &lt;/em&gt;&lt;/strong&gt;over the lifespan of the application between server restarts&lt;strong&gt;&lt;em&gt;. &lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, if you load them all at once, remember, SQL-wise, it’s only taking about 125ms to load. So if you created all 2500 instances of ParentName.cfc, you’ve got the 125ms for the SQL and whatever time it takes to create those 2500 component instances. In my case, it’s about a second, total. To achieve such a performance improvement, you run this when your app starts:&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EntityLoad(“ParentName”);&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Since ParentName is a cached component, it’ll get stuck in whatever cache you have configured in Application.cfc, and then all subsequent calls to organization.parentName() will take however long it would take to fetch a simple string from the cache. In my experience this is anywhere from 1/3 to 1 ms doing unscientific averaging.&lt;/p&gt;

&lt;p&gt;If you need to clear the cache, simply use:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ormEvictEntity(&amp;quot;ParentName&amp;quot;);&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;1) I was amazed at how easy it was to work with Hibernate’s second-level cache with ColdFusion ORM. It just worked. &lt;/p&gt;

&lt;p&gt;2) Sometimes, when you’re not &lt;a href="http://en.wikipedia.org/wiki/Joe_Celko" target="_blank"&gt;Joe Celko&lt;/a&gt; and you don’t want to spend time time figuring out how to write a better view, you say “you know what, I think I’ll see if there are fun and interesting bits in CF ORM that could solve this problem for me”. And then you go play, and you come up with some nifty things.&lt;/p&gt;

&lt;p&gt;3) I have no idea whether I’ll ever use this, but perhaps you’ll find a use for such a solution and, when you do, thank the CF team for doing such a fine job of integrating Hibernate’s L2 cache into CF.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;--Marc&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-91590053806630123?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/07/cf9-orm-using-secondary-cache-to.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-6220647513050264904</guid><pubDate>Sun, 11 Jul 2010 11:06:00 +0000</pubDate><atom:updated>2010-07-11T07:06:48.135-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>cfeclipse</category><category domain='http://www.blogger.com/atom/ns#'>eclipse</category><category domain='http://www.blogger.com/atom/ns#'>coldfusion builder</category><category domain='http://www.blogger.com/atom/ns#'>timesavers</category><title>How to set up a new Eclipse environment</title><description>&lt;p&gt;Have you ever wanted to start using a new version of Eclipse but couldn’t justify it because of all the time you’ve spent getting your preferences and project settings just so? And you don’t want to type in all those Update site URLs again to get all your plugins? While there is currently no one-click easy way to completely migrate an existing Eclipse install to a new one, I do have some timesavers for you.&lt;/p&gt;  &lt;h2&gt;Always start with a new Workspace&lt;/h2&gt;  &lt;p&gt;I’ve seen too many problems with trying to reuse an existing workspace in hopes of saving some time moving from an old version of Eclipse to a new one. Don’t do it. When you fire up the new Eclipse, and it asks you for the workspace, give it a new location. I keep a directory named “Eclipse Workspaces”, and in it lay the corpses of a dozen or more old workspaces. I name my workspaces with this general pattern:&lt;/p&gt;  &lt;p&gt;[Product]_[MajorVersionName]_[RCNumber]_[Purpose]&lt;/p&gt;  &lt;p&gt;For example, for my work projects, I use ColdFusion Builder on Galileo. My workspace is Bolt_Galileo_Work. When I was fiddling with some of the Helios (Eclipse 3.6) RCs, I was using Bolt_Helios_RC2_Work.&lt;/p&gt;  &lt;p&gt;For Eclipse Plugin development I use CFEclipse_Helios_PluginDevelopment. &lt;/p&gt;  &lt;p&gt;I always reserve the right to break that pattern.&lt;/p&gt;  &lt;h2&gt;Getting all your plugins&lt;/h2&gt;  &lt;p&gt;I’ve seen some people suggest copying them from the old install, and perhaps that works just fine. Here’s how I do it: I Export the update sites I want to install into my new Eclipse, and then Import them in the new one. Then, I install the plugins using the tried-and-true software installer. Here’s how:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In your old Eclipse&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Help – Install New Software &lt;/li&gt;    &lt;li&gt;Click the “Available Software Sites” link &lt;/li&gt;    &lt;li&gt;On the Available Software Sites screen, select the plugins that you want to install into your new Eclipse &lt;/li&gt;    &lt;li&gt;Click the “Export” button, and go through the dialog of saving the XML file someplace sensible, like your Desktop &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;That screen looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/__j-6QTK4wT8/TDmlxl_nXkI/AAAAAAAAATs/FsKy0vvW6Vw/s1600-h/updatesites%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="updatesites" border="0" alt="updatesites" src="http://lh5.ggpht.com/__j-6QTK4wT8/TDmlxyRol1I/AAAAAAAAATw/9r7Rsw0upgU/updatesites_thumb.png?imgmax=800" width="244" height="188" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In your new Eclipse&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Following the same steps as above, get to the Available Software Sites screen &lt;/li&gt;    &lt;li&gt;Click the “Import” button &lt;/li&gt;    &lt;li&gt;Navigate to that XML file you saved previously and follow all steps &lt;/li&gt;    &lt;li&gt;Now you have those update sites available to you. From there, get back to the Install software screen, select “All Software Sites” from the dropdown, and let Eclipse find and install all those plugins you know and love &lt;/li&gt; &lt;/ol&gt;  &lt;h2&gt;&amp;#160;&lt;/h2&gt;  &lt;h2&gt;Getting some of your Preferences&lt;/h2&gt;  &lt;p&gt;You can export some of your preferences from the old install to the new one, though you do have to beware that you’re going to import some preferences you don’t actually want. More on that in a bit.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In your old Eclipse&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;File – Export &lt;/li&gt;    &lt;li&gt;Select “Preferences” &lt;/li&gt;    &lt;li&gt;Follow the rest of the screens to save your prefs as an .epf file &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;In your new Eclipse&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;File – Import &lt;/li&gt;    &lt;li&gt;Select “Preferences” &lt;/li&gt;    &lt;li&gt;Follow the rest of the screens &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;As I said, it’s going to copy some preferences that you don’t want. In particular for me, I always get bitten by the “ANT Runtime” preferences. In that case, I let it do its thing, and then I go back into Window – Preferences and point the ANT runtime to the one that comes bundled with the new Eclipse. Even with that little annoyance, it’s worth it to export/import preferences because it brings over so much.&lt;/p&gt;  &lt;h2&gt;&amp;#160;&lt;/h2&gt;  &lt;h2&gt;Getting all your projects&lt;/h2&gt;  &lt;p&gt;Perhaps the most time-consuming part of moving to a new Eclipse installation is getting all your projects back in there. Fortunately, this can also be the &lt;strong&gt;least&lt;/strong&gt; time-consuming. Here’s what to do in your New Eclipse installation:&lt;/p&gt;  &lt;h3&gt;In CFEclipse&lt;/h3&gt;  &lt;ol&gt;   &lt;li&gt;File – Import &lt;/li&gt;    &lt;li&gt;Select “Existing Projects into Workspace”. Click Next &lt;/li&gt;    &lt;li&gt;In the “Select Root Directory” field, type in the directory where you keep most of your projects. Hit Enter &lt;/li&gt;    &lt;li&gt;Once it finds all the projects in that directory, choose the ones you want, and hit “Finish” &lt;/li&gt; &lt;/ol&gt;  &lt;h3&gt;In ColdFusion Builder&lt;/h3&gt;  &lt;p&gt;Follow the same steps as above, but at Step #2, choose “ColdFusion – Import existing Projects”&lt;/p&gt;  &lt;div class="note"&gt;NOTE: This will not copy &lt;strong&gt;All&lt;/strong&gt; of the existing properties for the projects, such as the MXUnit cfcpath and remote facade URL. For ColdFusion Builder, it will carry over the server settings since they are stored in a file that lives inside that project and not outside of it like most project properties in Eclipse&lt;/div&gt;  &lt;h2&gt;&amp;#160; &lt;/h2&gt;  &lt;h2&gt;Some Preferences I’m always sure to confirm&lt;/h2&gt;  &lt;p&gt;Once I’m finished with the above, I have a few preferences I always double-check. In Window – Preferences:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;General – Show Heap &lt;/li&gt;    &lt;li&gt;Quick Diff – Pristine SVN Copy &lt;/li&gt;    &lt;li&gt;Local History – at least 180 days &lt;/li&gt;    &lt;li&gt;Key Bindings – Alt-A for ANT view, Alt-S for CFEclipse Snip Tree View, and Alt-Y for Mylyn Task List view &lt;/li&gt;    &lt;li&gt;Appearance – Colors and Fonts – Basic Text --&amp;#160; Consolas 12pt &lt;/li&gt;    &lt;li&gt;CFEclipse / ColdFusion Builder Snippets path (I point it to a dropbox location)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If you have any quick tips for making migrating from one Eclipse installation to another less time-consuming, please share them.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-6220647513050264904?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/07/how-to-set-up-new-eclipse-environment.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-4511558950084991379</guid><pubDate>Fri, 09 Jul 2010 17:02:00 +0000</pubDate><atom:updated>2010-07-09T13:29:18.843-04:00</atom:updated><title>MXUnit 2.0 Released</title><description>Once again, Los Hombres at MXUnit.org are delivering a new batch of the crack cocaine of unit testing for ColdFusion--MXUnit 2.0.&amp;nbsp; Yes, it's true.&amp;nbsp; Once tasted, a life of uncontrollable and desperate automated testing will surely ensue. This particular batch has some especially addictive features:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;New Open Source License: &lt;i&gt;MIT&lt;/i&gt;. Changing from GPL to MIT effectively allows you to integrate MXUnit into any product with little restriction (other than honoring the &lt;i&gt;No Whining &lt;/i&gt;clause). &lt;/li&gt;
&lt;li&gt;New built-in mocking framework: Simply call the new &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mock()&lt;/span&gt; method to create a new mocked object and inject that into your component under test. &lt;/li&gt;
&lt;li&gt;New integrated HTML view: This replaces the existing HTML and ExtJS view and is backward compatible. &lt;/li&gt;
&lt;li&gt;New &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;beforeTests() &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;afterTests()&lt;/span&gt; for component-level set up and tear down. &lt;/li&gt;
&lt;li&gt;New and improved documentation and bug tracking at &lt;a href="http://wiki.mxunit.org/"&gt;http://wiki.mxunit.org&lt;/a&gt; and &lt;a href="http://jira.mxunit.org/"&gt;&lt;/a&gt;&lt;a href="http://jira.mxunit.org/secure/IssueNavigator.jspa?reset=true&amp;amp;mode=hide&amp;amp;pid=10000"&gt;http://jira.mxunit.org/secure/IssueNavigator.jspa?reset=true&amp;amp;mode=hide&amp;amp;pid=10000&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ant task improvement: now you can send arbitrary URL parameters to your custom runners.&lt;/li&gt;
&lt;li&gt;New Ant build.xml examples and Hudson-friendly examples. &lt;/li&gt;
&lt;li&gt;More Eclipse snippets! &lt;/li&gt;
&lt;li&gt;More Dataprovider improvements. &lt;/li&gt;
&lt;li&gt;Eclipse plugin data compare tool. &lt;/li&gt;
&lt;li&gt;Multiple Github fork(s) (&lt;a href="http://github.com/virtix/mxunit"&gt;http://github.com/virtix/mxunit&lt;/a&gt;). &lt;/li&gt;
&lt;li&gt;&lt;i&gt;Office Hours&lt;/i&gt; every other Monday at 12:00pm &lt;a href="http://www.timeanddate.com/worldclock/fixedtime.html?month=6&amp;amp;day=28&amp;amp;year=2010&amp;amp;hour=12&amp;amp;min=0&amp;amp;sec=0&amp;amp;p1=250"&gt;US Eastern Time&lt;/a&gt;. Join in via Adobe Connect and bring any testing or other technical questions or topics: &lt;a href="http://bit.ly/MXUnitOfficeHours"&gt;http://bit.ly/MXUnitOfficeHours&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;MXUnit couldn't deliver the kind of product it is without the generous help of many talented and dedicated programmers. This particular release saw significant contributions from these chefs:&lt;br /&gt;
&lt;br /&gt;
&lt;h5 style="font-weight: normal;"&gt;&lt;span style="font-size: small;"&gt;Tim Farrar&lt;/span&gt;&lt;/h5&gt;&lt;h5 style="font-weight: normal;"&gt;&lt;span style="font-size: small;"&gt;Peter Farrell&lt;/span&gt;&lt;/h5&gt;&lt;h5 style="font-weight: normal;"&gt;&lt;span style="font-size: small;"&gt;Patrick McElhaney&lt;/span&gt;&lt;/h5&gt;&lt;h5 style="font-weight: normal;"&gt;&lt;span style="font-size: small;"&gt;Randy Merrill &lt;/span&gt;&lt;/h5&gt;&lt;h5 style="font-weight: normal;"&gt;&lt;span style="font-size: small;"&gt;Bob Silverberg &lt;/span&gt;&lt;/h5&gt;&lt;h5 style="font-weight: normal;"&gt;&lt;span style="font-size: small;"&gt;John Whish&lt;/span&gt;&lt;/h5&gt;&lt;h5 style="font-weight: normal;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;
Cop the latest and greatest at &lt;a href="http://mxunit.org/download.cfm"&gt;http://mxunit.org/download.cfm&lt;/a&gt; and get involved &lt;a href="http://groups.google.com/group/mxunit"&gt;http://groups.google.com/group/mxunit&lt;/a&gt;&lt;/span&gt;&lt;/h5&gt;&lt;span style="font-size: small;"&gt;Test and be Happy!&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: small;"&gt;theguys at mxunit.org&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-4511558950084991379?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/07/mxunit-20-released.html</link><author>noreply@blogger.com (bill shelton)</author><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-340614381874197801</guid><pubDate>Mon, 21 Jun 2010 14:39:00 +0000</pubDate><atom:updated>2010-06-21T10:39:14.517-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>coldfusion</category><category domain='http://www.blogger.com/atom/ns#'>cfml</category><title>Your CFML Wish List</title><description>&lt;p&gt;For years, Adobe ColdFusion has added feature after feature that has dramatically improved productivity for CFML developers. With CF8, support for struct and array literals was added as well as improvements for operators (ability to use &amp;lt;= instead of LTE, ++ for incrementing, etc). With CF9, they added support for full-script CFCs. Well done, Adobe.&lt;/p&gt;  &lt;p&gt;I’d like to hear from you: what other enhancements would you like to see to the &lt;strong&gt;core language&lt;/strong&gt;? What drives you nuts that you wish you could change (var scope, cough cough). What is missing? What’s half-baked? I’m not talking about features or new tags or functionality … purely language-level stuff. As a &lt;strong&gt;coder&lt;/strong&gt;, what do you wish you could do with CFML that you can’t do today? Perhaps you’ve worked in other languages and encountered semantic constructs that you miss when working with CFML? &lt;/p&gt;  &lt;p&gt;This is strictly for my curiosity: I don’t work for Adobe, and I have exactly Zero Pull (tm). I have a list of enhancements I’d like to see made to CFML, and I’m curious how your wish list compares with mine.&lt;/p&gt;  &lt;p&gt;Thanks!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-340614381874197801?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/06/your-cfml-wish-list.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>15</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-888728345735775603</guid><pubDate>Mon, 21 Jun 2010 10:50:00 +0000</pubDate><atom:updated>2010-06-21T09:24:39.369-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>flex</category><category domain='http://www.blogger.com/atom/ns#'>flash builder</category><category domain='http://www.blogger.com/atom/ns#'>cfeclipse</category><category domain='http://www.blogger.com/atom/ns#'>eclipse</category><category domain='http://www.blogger.com/atom/ns#'>timesavers</category><title>A New Eclipse Timesaver for Flex, Java, and [insert language here] Developers</title><description>&lt;p&gt;CFML developers using CFEclipse (and&amp;#160; more recently ColdFusion Builder) have long enjoyed the benefits of Snippets and the Snip Tree View, a way to create customized, variable-driven chunks of code which you can drop into your source with a single keyboard combination. I wrote about them &lt;a href="http://blog.mxunit.org/2009/04/timesavers-cfeclipse-snippets.html" target="_blank"&gt;a long time ago&lt;/a&gt;, Matt Gifford recently wrote what has become the &lt;a href="http://www.mattgifford.co.uk/coldfusion-builder-snippets/" target="_blank"&gt;de facto guide to snippets&lt;/a&gt;, and lo many years back Mark Drew made &lt;a href="http://cfeclipse.org/assets/movies/07_Snippetsfla.html" target="_blank"&gt;this video which is still relevant today&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;To add to the general awesomeness of snippets, you can share them amongst your computers or even other developers. &lt;a href="http://blog.mxunit.org/2009/12/sharing-your-cfeclipse-coldfusion.html" target="_blank"&gt;This shows you how to do so with DropBox&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;In my experience, once a developer becomes snippet-infected, they tend to bemoan their absence when editing other types of source code. Unfortunately, Snippet insertion never worked when editing other files like Flex, and even when it did work, you had to install the entire CFEclipse plugin which some developers don’t want to do. Until now.&lt;/p&gt;  &lt;h2&gt;Who’s the target audience?&lt;/h2&gt;  &lt;p&gt;Flex, Java, JavaScript, Groovy, Scala, [insert your language here] developers who use Eclipse and who do not have ColdFusion Builder installed.* It’s also important that you like to save time.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;*ColdFusion Builder snippets should already work with other sources! Good job, CFB team.&lt;/strong&gt;&lt;/p&gt;  &lt;h2&gt;How do I install it?&lt;/h2&gt;  &lt;p&gt;The Eclipse Update Site is at &lt;a title="http://cfeclipse.org/snippets/update/" href="http://cfeclipse.org/snippets/update/"&gt;http://cfeclipse.org/snippets/update/&lt;/a&gt;. In Eclipse 3.5 and later, you’d use “Help – Install New Software”. Then click the “Add” Button. Then add that URL into the URL field. Follow through to the end.&lt;/p&gt;  &lt;h2&gt;What will this install into my Eclipse?&lt;/h2&gt;  &lt;p&gt;This will install a standalone Snippet Tree View and corresponding key binding into Eclipse. By default, the key binding is “Ctrl-Shift-I”. Note that this will be different from the binding mentioned in the above articles, although you can reassign it to whichever key combination you like. In FlashBuilder, I immediately reassigned mine to the familiar Ctrl-J sequence.&lt;/p&gt;  &lt;h2&gt;Who’s responsible for bringing such Joy unto the world?&lt;/h2&gt;  &lt;p&gt;We’d be remiss if we didn’t thank the CFEclipse founding fathers. &lt;a href="http://robrohan.com/" target="_blank"&gt;Rob Rohan&lt;/a&gt; and &lt;a href="http://twitter.com/spikefu" target="_blank"&gt;Spike Milligan&lt;/a&gt; will most likely never know that the work they did still continues to improve the lives of developers around the world. &lt;a href="http://www.markdrew.co.uk/blog/" target="_blank"&gt;Mark Drew&lt;/a&gt; has led CFEclipse for years and many credit him with helping make it a mature, stable platform on which to build CFML applications. And Robert Blackburn added the SnipEx support into the Snippet Tree View. Thanks to all you wonderful people!&lt;/p&gt;  &lt;p&gt;For this release -- separating Snippets into their own plugin and refactoring so that they’d be useful for other languages on the Eclipse platform --&amp;#160; &lt;a href="http://coldshen.com/blog/" target="_blank"&gt;Denny Valliant&lt;/a&gt; (&lt;a href="http://github.com/denuno" target="_blank"&gt;github&lt;/a&gt;) gets all the credit. Denny’s one of those guys you don’t hear much about, but he’s brought inestimable joy into developer lives through all the work he’s done on CFEclipse and other projects. Thank you, Denny.&lt;/p&gt;  &lt;h2&gt;What to do next?&lt;/h2&gt;  &lt;ol&gt;   &lt;li&gt;Install the Snippets Plugin &lt;/li&gt;    &lt;li&gt;Read one or more of the links above explaining how to use snippets. &lt;/li&gt;    &lt;li&gt;Open up the Snippet Tree View and add some snippets (don’t forget the “trigger text”!) &lt;/li&gt;    &lt;li&gt;Go into your editor and type the trigger text for one of the snippets you added. Hit Ctrl-Shift-I to insert the snippet &lt;/li&gt;    &lt;li&gt;Repeat Steps 3 and 4 and rejoice in all the time this will save you &lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-888728345735775603?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/06/new-eclipse-timesaver-for-flex-java-and.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-8460006354820877570</guid><pubDate>Sun, 23 May 2010 23:23:00 +0000</pubDate><atom:updated>2010-05-23T19:39:30.743-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>coldfusion</category><category domain='http://www.blogger.com/atom/ns#'>java</category><category domain='http://www.blogger.com/atom/ns#'>cfeclipse</category><category domain='http://www.blogger.com/atom/ns#'>eclipse</category><category domain='http://www.blogger.com/atom/ns#'>coldfusion builder</category><title>Creating a Hybrid ColdFusion – Java Project in Eclipse</title><description>&lt;p&gt;On more than one occasion recently I’ve wanted to incorporate Java libraries into ColdFusion applications. You can do this in your CFML, but it usually involves the following:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;CFML code littered with createObject(“java”,”whatever.Whatever”); &lt;/li&gt;    &lt;li&gt;Zero content assist for the Java objects &lt;/li&gt;    &lt;li&gt;Optionally, Putting jar files in your CF installation’s lib directories and deploying those to all servers (dev, test, staging, prod) and developer machines &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;1 and 2 are the worst problems because 3 is solved with Mark Mandel’s &lt;a href="http://www.compoundtheory.com/?action=javaloader.index" target="_blank"&gt;javaloader&lt;/a&gt; (more on that later).&lt;/p&gt;  &lt;p&gt;Ideally, I’d be able to write Java code in Java source files, compile it and test it in Eclipse, and fairly seamlessly use it in my CFML… &lt;em&gt;in the same project&lt;/em&gt;. In this post, I’ll show you how to set it up in ColdFusion Builder. Note that these same steps apply to CFEclipse as well. In a follow-up post, I’ll show a more real-world example&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Create your CFML project&lt;/h2&gt;  &lt;ol&gt;   &lt;li&gt;In CFBuilder or CFEclipse, either create a new project or use an existing one. &lt;/li&gt;    &lt;li&gt;Create a directory named “java”      &lt;ol&gt;       &lt;li&gt;under there, create “src”, “bin”, and “lib” directories &lt;/li&gt;        &lt;li&gt;Download &lt;a href="http://www.compoundtheory.com/?action=javaloader.index" target="_blank"&gt;javaloader&lt;/a&gt; from Mark’s site, and drag the “javaloader” directory into the root of your project (or put it in your webroot) &lt;/li&gt;        &lt;li&gt;If you put it into your project, add this to your Application.cfc: this.mappings[&amp;quot;/javaloader&amp;quot;] = getDirectoryFromPath(getCurrentTemplatePath()); &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;By now, your project should look something like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/__j-6QTK4wT8/S_m43T9CtkI/AAAAAAAAASk/Bnk5O-Ux4bE/s1600-h/HybridCFJavaStep1%5B5%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="HybridCFJavaStep1" border="0" alt="HybridCFJavaStep1" src="http://lh3.ggpht.com/__j-6QTK4wT8/S_m43qj_DmI/AAAAAAAAASo/L2xBovA13-E/HybridCFJavaStep1_thumb%5B3%5D.png?imgmax=800" width="629" height="251" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h2&gt;Apply the Java Nature&lt;/h2&gt;  &lt;ol&gt;   &lt;li&gt;Close the project: right click – “Close Project” &lt;/li&gt;    &lt;li&gt;From the file system, open the project’s “.project” file in a text editor &lt;/li&gt;    &lt;li&gt;In the “&amp;lt;natures&amp;gt;” element, add this: &amp;lt;nature&amp;gt;org.eclipse.jdt.core.javanature&amp;lt;/nature&amp;gt; &lt;/li&gt;    &lt;li&gt;In the “&amp;lt;buildSpec&amp;gt;” element, add the following: &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;/p&gt;  &lt;pre class="cf" name="code"&gt;&amp;lt;buildCommand&amp;gt;
	&amp;lt;name&amp;gt;org.eclipse.jdt.core.javabuilder&amp;lt;/name&amp;gt;
	&amp;lt;arguments&amp;gt;
	&amp;lt;/arguments&amp;gt;
&amp;lt;/buildCommand&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Back in Eclipse, open the project (right click -- “Open Project”). Once you do that, it’s going to look very strange… something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh6.ggpht.com/__j-6QTK4wT8/S_m44G3c0PI/AAAAAAAAASs/JPx4YJYUIjk/s1600-h/HybridCFJavaAllPackages%5B3%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="HybridCFJavaAllPackages" border="0" alt="HybridCFJavaAllPackages" src="http://lh5.ggpht.com/__j-6QTK4wT8/S_m45PvHWPI/AAAAAAAAASw/GXLthVm2fQk/HybridCFJavaAllPackages_thumb%5B1%5D.png?imgmax=800" width="619" height="338" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Configure the Java Build Path&lt;/h2&gt;

&lt;p&gt;Your project now looks funky because it’s treating everything as a Java source folder. Let’s fix that.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;On the project, right click, select “Build Path”, then “Configure Build Path” &lt;/li&gt;

  &lt;li&gt;In the “Source” tab, remove any entries &lt;/li&gt;

  &lt;li&gt;In the same tab, select “Add Folder” and navigate to your project’s “java/src” folder &lt;/li&gt;

  &lt;li&gt;Down at the bottom, in “Default output folder” text field, browse to your project’s “java/bin” directory &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, your project should look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh5.ggpht.com/__j-6QTK4wT8/S_m45b3Or1I/AAAAAAAAAS0/bYz3VR1XOYI/s1600-h/HybridCFJavaStep3%5B3%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="HybridCFJavaStep3" border="0" alt="HybridCFJavaStep3" src="http://lh3.ggpht.com/__j-6QTK4wT8/S_m45q2zRVI/AAAAAAAAAS4/Glz3xl1PM5c/HybridCFJavaStep3_thumb%5B1%5D.png?imgmax=800" width="307" height="237" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;That’s better.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Create a simple Java file&lt;/h2&gt;

&lt;p&gt;Note in that screenshot above that you have “java/src” with a package decorator… that’s where you’ll be working. Ignore the “java” directory that you see in that screenshot… we don’t care about it for now.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;In the “java/src” directory, right click, select “New – Package”. Name it “hello”. &lt;/li&gt;

  &lt;li&gt;In that (now empty) package, right click, select “New – Java Class”. Name it “Hello” &lt;/li&gt;

  &lt;li&gt;This will open a new Hello.java in a java editor. Let’s create a simple “echo” method. For now, just use a “main” method to drive it in Eclipse… we don’t need to get fancy with unit tests just yet: &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre class="java" name="code"&gt;package hello;

public class Hello {
	
	public String echo(String input){
		return &amp;quot;Hello. You said: &amp;quot; + input;
	}
	
	public static void main(String[] args) {
		Hello h = new Hello();
		System.out.println(h.echo(&amp;quot;marc&amp;quot;));
	}
	
}&lt;/pre&gt;

&lt;p&gt;If all goes well, you should be able to run this file and see output in the console. To run it, select “Hello.java” in the Project Explorer and hit the green “Play” button in the toolbar, or right click in Hello.java and select “run as – java application”, or hit “Alt-Shift-X, J&amp;quot;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;Use it in your CFML&lt;/h2&gt;

&lt;p&gt;To use it in your CFML, you’ll want to use javaloader. Conceptually, you simply tell javaloader where your compiled classes are, where any additional .jar files live, and then use it to create objects. Here’s what it looks like in practice. For demo purposes, I just created a file in my project root; thus, all paths you see in here are relative to that file in the root. &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;&amp;lt;!--- set up javaloader ---&amp;gt;
&amp;lt;cfset binDir = expandPath(&amp;quot;java/bin&amp;quot;)&amp;gt;
&amp;lt;cfset libDir = expandPath(&amp;quot;java/lib&amp;quot;)&amp;gt;
&amp;lt;cfset jars = directoryList(libDir)&amp;gt;
&amp;lt;cfset arrayAppend(jars,binDir)&amp;gt;
&amp;lt;cfset loader = createObject(&amp;quot;component&amp;quot;,&amp;quot;javaloader.JavaLoader&amp;quot;).init(jars)&amp;gt;

&amp;lt;!--- run it ---&amp;gt;
&amp;lt;h1&amp;gt;Hello!&amp;lt;/h1&amp;gt;

&amp;lt;h2&amp;gt;Echo example&amp;lt;/h2&amp;gt;
&amp;lt;cfset hello = loader.create(&amp;quot;hello.Hello&amp;quot;)&amp;gt;
&amp;lt;cfoutput&amp;gt;#hello.echo(&amp;quot;marc&amp;quot;)#&amp;lt;/cfoutput&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;If you’ve done everything right, when you run this in your browser you should see the expected output. If you go back into your java file, make a change, and hit refresh in the browser, the&amp;#160; changes you made should be reflected.&lt;/p&gt;

&lt;h2&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;For years, folk have praised the ability to integrate Java into CFML. However, the workflow has always been complicated and the tooling nonexistent. CFMLers who’ve worked for years without content assist on their own Components most likely have no idea just how powerful an ally their IDE can be. So we suffer, typing “whatever = createObject(“java”, “some.Java”); whatever.NowWhatWasThatMethodAgain(AndWhatWereThoseArgumentsAgain)”, not realizing that if we were writing our java in a “real” editor, you’d get all the richness the IDE can offer. In other words, most CFMLers don’t know what they’re missing when they have to incorporate java into their projects.&lt;/p&gt;

&lt;p&gt;I am not saying that when you create Java objects in your CFML code that you’re going to get content assist; rather, what I’m saying is that if you have more than a few lines of Java code in your CFML, then perhaps it’s best to put that code into its own Java sources – inside the same project, as I’ve described above – and &lt;strong&gt;simplify the work you have to do with Java without sacrificing workflow and deployment speed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It also opens up some other nice possibilities: If you’ve a Groovy fan, or have a problem that would be better suited for Groovy – yes… even if the thing you want to do is simply &lt;strong&gt;more enjoyable&lt;/strong&gt; in that language --- then you could do very similar steps to turn your CFML project into a hybrid Groovy project. Create your Whatever.g sources, and use Barney Boivert’s excellent &lt;a href="http://www.barneyb.com/barneyblog/projects/cfgroovy2/" target="_blank"&gt;CFGroovy&lt;/a&gt; to run your Groovy sources.&lt;/p&gt;

&lt;p&gt;If you need to write some java of your own, and you need to incorporate it into your CFML projects, then this IDE setup can help you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coming soon: a real-world example.&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-8460006354820877570?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/05/creating-hybrid-coldfusion-java-project.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-4700950209519577906</guid><pubDate>Fri, 07 May 2010 22:51:00 +0000</pubDate><atom:updated>2010-05-07T19:09:49.555-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>debugging</category><title>A Fun Bug in VMWare Workstation Installer</title><description>&lt;p&gt;I hit this fun bug this morning and wanted to share it. It’s quite unlikely that you’ll hit it yourself, so the value here is probably as much in the debugging as it is in helping folks down the road fix this should they find it via Googling.&lt;/p&gt;  &lt;h2&gt;The Problem&lt;/h2&gt;  &lt;p&gt;I clicked to install VMWare workstation, and was greeted with this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/__j-6QTK4wT8/S-SZbrxqNnI/AAAAAAAAASc/JXSTj-yJwKU/s1600-h/vmware%5B3%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="vmware" border="0" alt="vmware" src="http://lh5.ggpht.com/__j-6QTK4wT8/S-SZcN5cEoI/AAAAAAAAASg/xRqsoa7xdlg/vmware_thumb%5B1%5D.png?imgmax=800" width="244" height="187" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Yes, you’re seeing that correctly. Rather than seeing a normal installer window, I was looking at a Disney Vacation site. At first, I thought I must’ve had a virus on my computer but ruled that out pretty quickly. If it were a virus, I’d have been seeing pr0n or warez or some other such thing, not a Disney site… especially not a “static” Disney site.&lt;/p&gt;  &lt;h2&gt;Debugging the problem&lt;/h2&gt;  &lt;p&gt;The programmer in me isn’t thinking “Why isn’t this working?”. Instead, I’m thinking “What would cause an installer to display a Disney html file?”&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Some virus is hijacking the file and replacing it with the Disney file &lt;/li&gt;    &lt;li&gt;The VMWare installer is hosed &lt;/li&gt;    &lt;li&gt;The Real Answer &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;I wanted to explore the idea of something hijacking the file first. The question is… what file? This was easy to find. I simply looked in the VMWare workstation installer log and looked at what files it was unpacking and writing. Here’s a snippet:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;20100507074429:INFO CPackageManager::GetFile: index.htm 20100507074429:INFO CHtmlUI::SetHtmlFile: Navigating from '' to 'C:\Users\Marc\AppData\Local\Temp\vmware_1273232669\index.htm' 20100507074429:INFO CHtmlDialog::NavigateToFile: Loading file C:\Users\Marc\AppData\Local\Temp\vmware_1273232669\index.htm?lang=1033&amp;amp;locale=1033 &lt;/code&gt;&lt;/p&gt;  &lt;p&gt;I opened that index.htm file and sure enough, it was the Disney html. So, off to see what activity was happening around index.htm. To do that, I used &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx" target="_blank"&gt;Sysinternals Process Monitor&lt;/a&gt;. This simply involved firing it up and adding a filter for index.htm to get rid of the copious noise that Process Monitor spits out by default.&lt;/p&gt;  &lt;p&gt;Looking at the output, the answer became obvious. The first instance of an index.htm was in c:\&amp;lt;path_to_my_downloads&amp;gt;\index.htm.&amp;#160; Then I saw the index.htm in the temp directory. Ahhh…. so the installer was creating a file in the same directory in which it lived and then copying it into the temp directory.&lt;/p&gt;  &lt;p&gt;I’m sure you see where this is going.&lt;/p&gt;  &lt;p&gt;I headed to my downloads directory, and there she was… index.htm, Disney-fied. &lt;/p&gt;  &lt;h2&gt;How does this happen?&lt;/h2&gt;  &lt;p&gt;You might be wondering how in the heck that Disney index.htm file might have gotten in my downloads folder. The answer is simple: I have kids. If you’ve ever watched a kid use an internet browser, you’ll see them mousing around and doing all manner of weird draggy things that inevitably involves downloading a bunch of web files (usually images, but occasionally they can manage html files) into wherever you have configured downloads to go. It’s usually harmless. &lt;/p&gt;  &lt;p&gt;In this case, you can probably imagine the code in the installer: “if !fileExists…, write index.htm” …. “copy index.htm to temp\vmware_blahblah\index.htm”&lt;/p&gt;  &lt;p&gt;But why would you, the installer writer (or the program that emits the installers), fail to handle the case when there could already be a file like that in the place where downloads go?&amp;#160; It’s a stretch, and that’s why this is such a fun bug.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-4700950209519577906?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/05/bug-in-vmware-workstation-installer.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-5451881462611631286</guid><pubDate>Thu, 29 Apr 2010 01:26:00 +0000</pubDate><atom:updated>2010-04-28T21:26:59.897-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>CFUnited</category><category domain='http://www.blogger.com/atom/ns#'>cfObjective</category><category domain='http://www.blogger.com/atom/ns#'>BOF</category><category domain='http://www.blogger.com/atom/ns#'>conferences</category><title>BOFs: An Opinion</title><description>&lt;p&gt;Most conferences nowadays have BOFs, “Birds of a Feather” sessions usually held after-hours on one or more nights of the conference. These are informal get-togethers where folk sit around and talk about a topic. These topics are usually set in advance, either by conference organizers or existing speakers. Like most conference sessions, attendance varies. This is my experience with BOFs, at any rate.&lt;/p&gt;  &lt;p&gt;This year, at cf.Objective, Bob Silverberg asked if I’d coordinate a Test-Driven-Development (TDD) BOF with him. I accepted. I expected a handful of people. I was wrong in this expectation. It started small but quickly got way too big for normal BOF comfort. See, the problem isn’t with the number of people who attend: I was thrilled to see so many people. I do not know “how well” we did but I give us a “C”. The reason for this mediocre assessment is the subject of this post.&lt;/p&gt;  &lt;p&gt;A BOF should be a place where you, the attendee, go with either A) some interest or B) a burning question. If you’re in Camp A, then all you should expect from a BOF is exposure to ideas. If you’re in Camp B, then I think you should get something approximating an answer to that question. If not “the answer”, then at least guidance. But when BOFs get too big, it’s unlikely you’ll get that. Lots of things stand in your way, probably the most prominent of which is one or two topics (and people) dominating the conversation. It’s what humans do, and I won’t put upon a BOF some expectation that it transcend humanity.&lt;/p&gt;  &lt;p&gt;In our BOF, we had at least three burning questions: &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;What is TDD and how do I get started?&lt;/li&gt;    &lt;li&gt;How do I test database interaction (and perhaps other network-bound services)?&lt;/li&gt;    &lt;li&gt;How does TDD improve API design? (this is what I wanted to discuss, by the way)&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;A fourth lingering one was “How do I test ‘the entire app’?”, i.e. how does unit testing differ from integration testing (note that this has nothing to do with TDD at all).&lt;/p&gt;  &lt;p&gt;This is simply too many needs to be met in an hour in a traditional BOF.&lt;/p&gt;  &lt;h2&gt;What a BOF should be&lt;/h2&gt;  &lt;p&gt;So what should a BOF be? If you’re in Camp B, it should be small and focused. BOFs sprung up lo those many years ago as a reaction to typical eyes-forward conference sessions. They’re a way to bring people together around a topic where everyone gets a chance to talk, not just a speaker. They are a discussion. They attempt to imbue a sense of the “hallway conversation” that conference-goers love to rave about. When BOFs get too big, they have failed this mission. Why is this? Perhaps it’s simply that anything that gets too successful becomes a victim of its own success. Let’s fix this.&lt;/p&gt;  &lt;h2&gt;How BOFs should be organized&lt;/h2&gt;  &lt;p&gt;BOFs should not be organized ahead of time, especially by conference organizers or speakers. Oh, I’ll&amp;#160; make an exception for “Meet the Team” events that you get at large conferences like Adobe MAX. Otherwise, they should be organic. This is simpler than it sounds. Here’s a recipe:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;At the beginning of the conference, put a chalkboard or whiteboard out in some open space. At smaller conferences like cf.Objective, this is in the lobby adjacent to the conference rooms. In a larger conferences such as MAX, this is … the same thing.&lt;/li&gt;    &lt;li&gt;Promote the chalkboard ahead of time, in emails to attendees, signage, Twitter, and other means. Make it obvious that this chalkboard thing is where you go to suggest BOFs&lt;/li&gt;    &lt;li&gt;Organizers can put headers on the Chalkboard: D1, D2, D3, C1, C2, “The Bar”, “The Bar with fancy Tequilas”… etc.&amp;#160; These are the available spaces. Call them D1:8pm and D2:9pm if you have multiple time slots&lt;/li&gt;    &lt;li&gt;People interested in a topic can write it under one of the slots. People who see a topic they’re interested in can put a line or some other marker underneath a topic to signify their interest in attending. Nothing fancy. Numbers don’t matter. &lt;strong&gt;A BOF of two is just as important as a BOF of 10&lt;/strong&gt;.&lt;/li&gt;    &lt;li&gt;At the time of each BOF session, people meet in the room and ask around to see who’s here for what BOF. My gut says self-organization at start time will take no more than 5 minutes&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;In our TDD BOF, I wish we had course-corrected immediately… I wish we had realized the interests in the room and asked people if they wanted to break out into smaller groups. Unfortunately, at that time, it probably would’ve been too late. We’d have first had to figure out what those interests were and then hope that a leader emerged (by leader, I mean “the person who says ‘let’s go over to this set of chairs’).&amp;#160; If we were more prepared, we could have had an idea of what kinds of things people might be interested in and when we saw the group get large (this didn’t happen until about 10 minutes in, by the way), we could’ve thrown out those topics for show-of-hands and then broken out. But you should already see why this is a failure in the making: it’s an inappropriate time for such a thing, considering by the time “real talk” started, we’d have been 15 minutes into it because ad-hoc organization is always more chaotic than if the organization had been happening – on the chalkboard – all week long.&lt;/p&gt;  &lt;h2&gt;There is a precedent&lt;/h2&gt;  &lt;p&gt;If this sounds strange to you… if this violates some sense of control that you feel needs to be exerted by those-in-charge, know that what I’m proposing here isn’t an original thought, and it’s not untested. In fact, entire conferences are run this way (Google “open space conference”). The entire Java Posse roundup is largely run this way, and it’s a smashing success (not because of attendance numbers, but by a far more important criteria… attendee reaction).&lt;/p&gt;  &lt;h2&gt;Imagine&lt;/h2&gt;  &lt;p&gt;You go to an eyes-forward conference and you have a list of topics to attend during normal hours. But you also have a burning question. You put it on a board. One other person comes. You talk for an hour about your shared interest. You might learn something, teach something, make a friend, make an acquaintance, learn “I can’t stand this person”, learn “I want to start a business with this person”. Maybe you yank out a laptop and code for an hour together. You never know where it might lead. It’s unpredictable, and energetic.&lt;/p&gt;  &lt;p&gt;That’s the kind of spontaneity that is the hallmark of a great BOF.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Conference organizers: make it happen.&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-5451881462611631286?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/04/bofs-opinion.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>6</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-7904196162851123090</guid><pubDate>Thu, 01 Apr 2010 21:50:00 +0000</pubDate><atom:updated>2010-04-01T17:52:30.923-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>cfeclipse</category><category domain='http://www.blogger.com/atom/ns#'>eclipse</category><category domain='http://www.blogger.com/atom/ns#'>coldfusion builder</category><title>Changing ColdFusion Builder file encoding</title><description>&lt;p&gt;A few of our source code files contain Spanish text strings and smart quotes (i.e. curly quotes) copied from MSWord and pasted into Eclipse. These “special characters” have never caused problems in CFEclipse, but they were showing up as little boxes in CFBuilder:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/__j-6QTK4wT8/S7UVNvyfA1I/AAAAAAAAASM/xmV1GSJnj54/s1600-h/cfbuilder_encoding_1%5B2%5D.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="cfbuilder_encoding_1" border="0" alt="cfbuilder_encoding_1" src="http://lh3.ggpht.com/__j-6QTK4wT8/S7UVNxlqdII/AAAAAAAAASQ/6uhAPxgIftE/cfbuilder_encoding_1_thumb.png?imgmax=800" width="260" height="72" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I knew it was a file encoding issue but couldn’t solve it. The default text file encoding (window – preferences – general – workspace -– Text file encoding) was &lt;a href="http://en.wikipedia.org/wiki/Windows-1252" target="_blank"&gt;Cp1252&lt;/a&gt;, which was the same as CFE. However, viewing the properties of a file showed that the file was &lt;a href="http://en.wikipedia.org/wiki/Utf-8" target="_blank"&gt;UTF-8&lt;/a&gt; in CFBuilder but still Cp1252 in CFEclipse.&lt;/p&gt;  &lt;p&gt;To get CFBuilder to behave like CFEclipse with respect to file encoding:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Window – preferences – general – Content Types&lt;/li&gt;    &lt;li&gt;Expand the “Text” tree&lt;/li&gt;    &lt;li&gt;Select “CFML Source File”&lt;/li&gt;    &lt;li&gt;Down at the bottom, change the Default encoding&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/__j-6QTK4wT8/S7UVOQODEvI/AAAAAAAAASU/GNKkCW8cp60/s1600-h/cfbuilder_encoding%5B2%5D.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="cfbuilder_encoding" border="0" alt="cfbuilder_encoding" src="http://lh4.ggpht.com/__j-6QTK4wT8/S7UVO_vnYXI/AAAAAAAAASY/C0ZZ9IUPh3k/cfbuilder_encoding_thumb.png?imgmax=800" width="218" height="260" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Warning: I wouldn’t change this setting unless you’re experiencing this problem yourself. &lt;/strong&gt;To be clear, this falls into the “if you must do dumbass stuff like copy text from Word into Eclipse and retain the funky characters, then here’s how to fix it”&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-7904196162851123090?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/04/changing-coldfusion-builder-file.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>4</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-4255844921341345296</guid><pubDate>Thu, 01 Apr 2010 21:15:00 +0000</pubDate><atom:updated>2010-04-01T17:29:43.884-04:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>jira</category><category domain='http://www.blogger.com/atom/ns#'>Best Practices</category><title>Jira: Creating a custom description template</title><description>&lt;p&gt;It’s hard work getting your team to enter bugs/issues into your issue tracker (“can’t I could just email you?”), and it’s even more difficult getting them to provide enough description to make the issue summary helpful. As the person who’s job it is to report issues to you, they need to “transfer context”. They know this bug intimately, either because they found it themselves or a customer/user reported it to them.&lt;/p&gt;  &lt;p&gt;You – our heroic developer – don’t know anything about the issue. They want you to fix it quickly, and you want to fix it quickly… so why is it so damn hard to get them to understand that the more detail they provide, the faster you both get what you want?&lt;/p&gt;  &lt;p&gt;I don’t have any good answers to that question, but I’m hoping this tip can help you incent them to give you more of what you need.&lt;/p&gt;  &lt;h2&gt;Editing the Description textarea&lt;/h2&gt;  &lt;p&gt;Often, you want users to enter the following:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;a link to the page that’s causing troubles &lt;/li&gt;    &lt;li&gt;relevant IDs (order ID, for example) &lt;/li&gt;    &lt;li&gt;a description of the behavior they expected &lt;/li&gt;    &lt;li&gt;a description of the actions they took that resulted in the unexpected behavior &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Here’s what my description template looks like:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/__j-6QTK4wT8/S7UNByTIixI/AAAAAAAAASE/BG4QZm69zdc/s1600-h/jira_description%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="jira_description" border="0" alt="jira_description" src="http://lh4.ggpht.com/__j-6QTK4wT8/S7UNCLKKNYI/AAAAAAAAASI/bhYV2JN8ktw/jira_description_thumb.png?imgmax=800" width="260" height="73" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You probably have others. To Pre-populate your with a customized template:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Navigate to your jira install directory. Drill down to WEB-INF\classes\templates\jira\issue\field &lt;/li&gt;    &lt;li&gt;Save a copy of description-edit.vm (to be safe) &lt;/li&gt;    &lt;li&gt;Edit description-edit.vm, like so: &lt;/li&gt; &lt;/ol&gt;  &lt;pre&gt;#controlHeader ($action $field.id $i18n.getText($field.nameKey) $fieldLayoutItem.required $displayParameters.get('noHeader'))

## setup some additional parameters
$!rendererParams.put(&amp;quot;rows&amp;quot;, &amp;quot;12&amp;quot;)
$!rendererParams.put(&amp;quot;wrap&amp;quot;, &amp;quot;virtual&amp;quot;)

## marc's custom hoogie
#macro( setDescription )
-- All your custom stuff goes here --
SYSTEM: Dev  |  Test   |   Staging |  PROD

LINK TO DEMONSTRATE BEHAVIOR:

ACTUAL BEHAVIOR:

EXPECTED BEHAVIOR:

STEPS TO REPRODUCE:
-- your custom stuff ends here --
#end

## let the renderer display the edit component

#if ($description==&amp;quot;&amp;quot; || !$description)
#set ($description = &amp;quot;#setDescription()&amp;quot;)
#end

$rendererDescriptor.getEditVM($!description, $!issue.key, $!fieldLayoutItem.rendererType, $!field.id, $!field.name, $rendererParams, false)

#controlFooter ($action $fieldLayoutItem.getFieldDescription() $displayParameters.get('noHeader'))&lt;/pre&gt;

&lt;p&gt;Restart Jira&lt;/p&gt;

&lt;p&gt;That’s it!&lt;/p&gt;

&lt;p&gt;You can read more about &lt;a href="http://confluence.atlassian.com/display/JIRA/Modifying+JIRA+Templates+and+JSPs" target="_blank"&gt;customizing Jira templates here&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-4255844921341345296?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/04/jira-creating-custom-description.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-1124005938158335947</guid><pubDate>Wed, 03 Mar 2010 12:28:00 +0000</pubDate><atom:updated>2010-03-03T07:28:33.441-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>cfeclipse</category><category domain='http://www.blogger.com/atom/ns#'>coldfusion builder</category><category domain='http://www.blogger.com/atom/ns#'>mylyn</category><category domain='http://www.blogger.com/atom/ns#'>timesavers</category><title>Mylyn: Creating new Issues from TODO comments</title><description>&lt;p&gt;On Twitter, the Eclipse PDE lead commented on a neat feature of Mylyn that I hadn’t seen before: the ability to add issues/bugs into your issue tracker directly from the “Problems” view. I wanted to see if you could do this from the “Tasks” view if you entered “TODO” comments into your CFML, and sure enough, it works. As of this writing, CFEclipse supports TODO tasks but ColdFusion Builder does not. &lt;a href="http://cfbugs.adobe.com/bugreport/flexbugui/cfbugtracker/main.html#bugId=74931" target="_blank"&gt;Please consider voting for this feature request&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;What I love about this feature is that you can fairly seamlessly create tasks and attach your context for that new task in less than a minute. When executives yammer on about “Work Smarter, Not Harder”, Mylyn features such as this exemplify the “work smarter” mentality. The point here is that you reduce friction in two areas: 1) creating the task with relevant information, 2) sharing your context with the developer to whom you’re assigning the task. &lt;/p&gt;  &lt;p&gt;Reduced friction == Increased Productivity. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Here’s how:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;object id="scPlayer" width="636" height="479"&gt; &lt;param name="movie" value="http://content.screencast.com/users/MarcEsher/folders/Jing/media/6e5da5f9-aa5d-438f-b275-416829728d0d/jingswfplayer.swf"&gt;&lt;/param&gt; &lt;param name="quality" value="high"&gt;&lt;/param&gt; &lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;/param&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/MarcEsher/folders/Jing/media/6e5da5f9-aa5d-438f-b275-416829728d0d/FirstFrame.jpg&amp;amp;containerwidth=636&amp;amp;containerheight=479&amp;amp;content=http://content.screencast.com/users/MarcEsher/folders/Jing/media/6e5da5f9-aa5d-438f-b275-416829728d0d/2010-03-03_0711.swf"&gt;&lt;/param&gt; &lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt; &lt;param name="scale" value="showall"&gt;&lt;/param&gt; &lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt; &lt;param name="base" value="http://content.screencast.com/users/MarcEsher/folders/Jing/media/6e5da5f9-aa5d-438f-b275-416829728d0d/"&gt;&lt;/param&gt;  &lt;embed src="http://content.screencast.com/users/MarcEsher/folders/Jing/media/6e5da5f9-aa5d-438f-b275-416829728d0d/jingswfplayer.swf" quality="high" bgcolor="#FFFFFF" width="636" height="479" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/users/MarcEsher/folders/Jing/media/6e5da5f9-aa5d-438f-b275-416829728d0d/FirstFrame.jpg&amp;containerwidth=636&amp;containerheight=479&amp;content=http://content.screencast.com/users/MarcEsher/folders/Jing/media/6e5da5f9-aa5d-438f-b275-416829728d0d/2010-03-03_0711.swf" allowFullScreen="true" base="http://content.screencast.com/users/MarcEsher/folders/Jing/media/6e5da5f9-aa5d-438f-b275-416829728d0d/" scale="showall"&gt;&lt;/embed&gt; &lt;/object&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In Words:&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;In CFEclipse, enter a TODO comment in your source code, Something like &amp;lt;!--- TODO: make this thing actually work ---&amp;gt;&lt;/li&gt;    &lt;li&gt;Open the “Tasks” view – notice your TODO is now in the that view as a new task&lt;/li&gt;    &lt;li&gt;Right click on that table row, and select “New Task from Marker”&lt;/li&gt;    &lt;li&gt;This will bring up the screens necessary to add the issue to your issue tracker (or enter as a “Local task” if not using an issue tracker)&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;To then attach that file as the “context” for the issue:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Activate the new task&lt;/li&gt;    &lt;li&gt;Navigate back to your file that contains the “TODO”. This file will now be part of the context for the issue&lt;/li&gt;    &lt;li&gt;In the Issue editor, go to the “context” tab and click the “Attach Context…” link. Follow the steps to completion&lt;/li&gt;    &lt;li&gt;Note that this is the &lt;a href="http://blog.mxunit.org/2010/03/mylyn-and-jira-sharing-context-with.html" target="_blank"&gt;same thing I wrote about previously&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Now, when the developer to whom the issue is assigned (even if it’s you) opens this issue, they’ll be able to retrieve the context and get working on the file you want them to work on without having to navigate a single tree. &lt;/p&gt;  &lt;p&gt;If this ain’t Jedi effect smoothness, I don’t know what is.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Happy Coding.&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-1124005938158335947?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/03/mylyn-creating-new-issues-from-todo.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>7</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-6614860331189949053</guid><pubDate>Tue, 02 Mar 2010 12:40:00 +0000</pubDate><atom:updated>2010-03-02T07:40:31.218-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>cfeclipse</category><category domain='http://www.blogger.com/atom/ns#'>coldfusion builder</category><category domain='http://www.blogger.com/atom/ns#'>mylyn</category><category domain='http://www.blogger.com/atom/ns#'>timesavers</category><title>Mylyn and Jira: Sharing Context with Another Developer</title><description>&lt;p&gt;When working on a team of developers, it sometimes is useful to reassign an issue to another developer. In Jira, you simply hit the “Reassign” link; this is standard amongst all issue trackers worth their salt.&lt;/p&gt;  &lt;p&gt;Wouldn’t it be nice if you could also copy your Mylyn context? If you could say “I’ve been working on these 5 files, and when I reassign this issue to you, you’re going to get the same view of the world as me so you don’t have to figure out what files are involved in this issue”?&lt;/p&gt;  &lt;p&gt;Here’s how:&lt;/p&gt;  &lt;p&gt;&lt;object id="scPlayer" width="640" height="495"&gt; &lt;param name="movie" value="http://content.screencast.com/users/MarcEsher/folders/Default/media/63f52efa-5042-4c12-bdb8-cb8cab8c7e5f/bootstrap.swf"&gt;&lt;/param&gt; &lt;param name="quality" value="high"&gt;&lt;/param&gt; &lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;/param&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/MarcEsher/folders/Default/media/63f52efa-5042-4c12-bdb8-cb8cab8c7e5f/FirstFrame.jpg&amp;amp;containerwidth=640&amp;amp;containerheight=495&amp;amp;content=http://content.screencast.com/users/MarcEsher/folders/Default/media/63f52efa-5042-4c12-bdb8-cb8cab8c7e5f/MylynCopyContext.swf"&gt;&lt;/param&gt; &lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt; &lt;param name="scale" value="showall"&gt;&lt;/param&gt; &lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt; &lt;param name="base" value="http://content.screencast.com/users/MarcEsher/folders/Default/media/63f52efa-5042-4c12-bdb8-cb8cab8c7e5f/"&gt;&lt;/param&gt;  &lt;embed src="http://content.screencast.com/users/MarcEsher/folders/Default/media/63f52efa-5042-4c12-bdb8-cb8cab8c7e5f/bootstrap.swf" quality="high" bgcolor="#FFFFFF" width="640" height="495" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/users/MarcEsher/folders/Default/media/63f52efa-5042-4c12-bdb8-cb8cab8c7e5f/FirstFrame.jpg&amp;containerwidth=640&amp;containerheight=495&amp;content=http://content.screencast.com/users/MarcEsher/folders/Default/media/63f52efa-5042-4c12-bdb8-cb8cab8c7e5f/MylynCopyContext.swf" allowFullScreen="true" base="http://content.screencast.com/users/MarcEsher/folders/Default/media/63f52efa-5042-4c12-bdb8-cb8cab8c7e5f/" scale="showall"&gt;&lt;/embed&gt; &lt;/object&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In Words&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;In ColdFusion Builder or Eclipse, In the Issue editor for a given issue, go to the “Context” tab&lt;/li&gt;    &lt;li&gt;It will show you all the elements associated with your context&lt;/li&gt;    &lt;li&gt;In the upper left, Click the “Attach Context” link. Follow to completion. This will attach your context to the Jira issue&lt;/li&gt;    &lt;li&gt;When the other developer working on the issue activates it, Mylyn will recognize that they do not have any context for the issue yet and will prompt them to open your context.&lt;/li&gt;    &lt;li&gt;When they do so, it’ll open up just the files you had attached to the context&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Awesome!&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Big Caveat: This relies on both developers having projects that are named the same&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-6614860331189949053?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/03/mylyn-and-jira-sharing-context-with.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-8825293080045984756</guid><pubDate>Mon, 01 Mar 2010 14:16:00 +0000</pubDate><atom:updated>2010-03-01T09:28:08.495-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>cfeclipse</category><category domain='http://www.blogger.com/atom/ns#'>coldfusion builder</category><category domain='http://www.blogger.com/atom/ns#'>mylyn</category><title>Mylyn and Jira: A Short Tutorial</title><description>&lt;p&gt;Recently, I wrote about why I believe &lt;a href="http://blog.mxunit.org/2010/02/why-mylyn-is-indispensible.html" target="_blank"&gt;Mylyn is an indispensable tool&lt;/a&gt; for developers on the Eclipse platform – this includes CFEclipse and ColdFusion Builder users. I also wrote about my &lt;a href="http://blog.mxunit.org/2010/02/best-eclipse-menu-youve-never-heard-of.html" target="_blank"&gt;favorite Mylyn-related toolbar&lt;/a&gt; item.&lt;/p&gt;  &lt;p&gt;Today, I created a screencast that quickly shows how to link Mylyn to a Jira instance:&lt;/p&gt;  &lt;p&gt;&lt;object width="500" height="405"&gt;&lt;param name="movie" value="http://www.youtube.com/v/z4ZfaPPk9HU&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;hd=1&amp;amp;border=1"&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/z4ZfaPPk9HU&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;hd=1&amp;amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="500" height="405"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In Words:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In Eclipse or ColdFusion Builder:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Window – Show View – Task Repositories &lt;/li&gt;    &lt;li&gt;Right click in the view and select “Add Task Repository” &lt;/li&gt;    &lt;li&gt;Select “Jira”. If it’s not in the list, hit the “Install More Connectors” button and install the Atlassian&amp;#160; Connector from there &lt;/li&gt;    &lt;li&gt;Hit “Next” &lt;/li&gt;    &lt;li&gt;Enter the URL to your jira install, label it, and enter your credentials &lt;/li&gt;    &lt;li&gt;Expand “Additional Settings”. &lt;/li&gt;    &lt;li&gt;I like to set the “Refresh Configuration Automatically” checkbox and I limit the search results to 100. Do whatever you like &lt;/li&gt;    &lt;li&gt;Hit the “Validate Settings” button at the bottom. Then hit “Finish” &lt;/li&gt;    &lt;li&gt;It’ll prompt you to pull in a Query from Jira. These will be your saved filters, which will include Jira’s default filters in addition to any custom filters you’ve created &lt;/li&gt;    &lt;li&gt;Select a filter or create&amp;#160; a new query. Hit enter and wait for them to load. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Exult!&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Once you’ve done that initial bit of setup, you’re ready to rock. You can now work with Mylyn from the “Task list” view (this will be your main Mylyn view). If you want to include other filters, do this:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;From the “Task List” view, right click and select “New Query” &lt;/li&gt;    &lt;li&gt;Select your jira install, and hit Next &lt;/li&gt;    &lt;li&gt;You can create a new query with the query builder form, OR: &lt;/li&gt;    &lt;li&gt;You can use a saved filter from your Jira Install. I like this method &lt;/li&gt;    &lt;li&gt;Select the “use saved filter” radio button, and select a filter. If you’ve added one that doesn’t show up in the list, hit the “Update from repository” button &lt;/li&gt;    &lt;li&gt;Hit “Finish” &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Your filter will now show up as a new tree item in the Task List view&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Happy Mylyn-ing!&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-8825293080045984756?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/03/mylyn-and-jira-short-tutorial.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>4</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-3403474908169631080</guid><pubDate>Mon, 01 Mar 2010 13:16:00 +0000</pubDate><atom:updated>2010-03-01T08:16:19.820-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>cfeclipse</category><category domain='http://www.blogger.com/atom/ns#'>coldfusion builder</category><category domain='http://www.blogger.com/atom/ns#'>timesavers</category><title>ColdFusion Builder: Importing existing projects into a new workspace</title><description>&lt;p&gt;In ColdFusion builder and CFEclipse, I like to keep my workspace “light”, meaning I keep only a few open projects in the workspace at any one time. When it becomes necessary to work on a previous project that isn’t in my workspace, I “import” that project back in.&lt;/p&gt;  &lt;p&gt;This method is also useful when you have already created projects in CFBuilder or CFEclipse and you want to use them in a new workspace. The “long” way would be to start a new workspace and then to do File – New – Create Project… for all the projects that you’ve already created.&lt;/p&gt;  &lt;p&gt;The fast way is to simply “Import” them. I whipped up a screencast to demonstrate this:&lt;/p&gt;  &lt;p&gt;&lt;object width="660" height="525"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Y8XEntKHrXY&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;hd=1&amp;amp;border=1"&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/Y8XEntKHrXY&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;hd=1&amp;amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="660" height="525"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In words:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In ColdFusion Builder or CFEclipse:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;File – Import – Existing Projects into Workspace &lt;/li&gt;    &lt;li&gt;Type the directory where your project lives.      &lt;ol&gt;       &lt;li&gt;If you want the option to import ALL projects in your webroot, you could simply type the location of your webroot – for example, c:\inetpub\wwwroot. This will take a while since it will scan every directory for .project files &lt;/li&gt;        &lt;li&gt;Alternately, if you know which directories your project lives in, you could do them one at a time &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;Hit Enter &lt;/li&gt;    &lt;li&gt;Hit Finish &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;em&gt;Special Thanks to &lt;a href="http://nodans.com/" target="_blank"&gt;Dan Wilson&lt;/a&gt; for suggesting this tutorial&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-3403474908169631080?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/03/coldfusion-builder-importing-existing.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-5534025250080020149</guid><pubDate>Sat, 27 Feb 2010 23:12:00 +0000</pubDate><atom:updated>2010-02-28T09:39:06.418-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>coldfusion</category><category domain='http://www.blogger.com/atom/ns#'>cfeclipse</category><category domain='http://www.blogger.com/atom/ns#'>eclipse</category><category domain='http://www.blogger.com/atom/ns#'>coldfusion builder</category><category domain='http://www.blogger.com/atom/ns#'>mylyn</category><category domain='http://www.blogger.com/atom/ns#'>timesavers</category><title>Why Mylyn is Indispensable</title><description>&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; This post isn’t meant to be an exhaustive exploration of Mylyn for ColdFusion developers; rather, it’s a quick dive into why I love it and would not want to work without it.&lt;/p&gt;  &lt;h2&gt;What is Mylyn&lt;/h2&gt;  &lt;p&gt;Mylyn is an Eclipse plugin that works with both ColdFusion Builder and CFEclipse.&lt;/p&gt;  &lt;p&gt;From the &lt;a href="http://www.eclipse.org/mylyn/" target="_blank"&gt;Mylyn&lt;/a&gt; home page:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“Mylyn is a &lt;a href="http://en.wikipedia.org/wiki/Task-focused_interface"&gt;task-focused interface&lt;/a&gt; for Eclipse that reduces information overload and makes multi-tasking easy. It does this by making tasks a first class part of Eclipse, and integrating rich and offline editing for repositories such as Bugzilla, Trac, and JIRA. Once your tasks are integrated, Mylyn monitors your work activity to identify relevant information, and uses this task context to focus the user interface on the task-at-hand. This puts the information you need at your fingertips and improves productivity by reducing searching, scrolling, and navigation. By making task context explicit Mylyn also facilitates multitasking, planning, reusing past efforts, and sharing expertise.”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;For me, this means:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Noise reduction &lt;/li&gt;    &lt;li&gt;Easy context switching and context reconstitution &lt;/li&gt;    &lt;li&gt;Easy “context sharing” &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;All of this happens in the context of “tasks”. This might be a bug, a new feature, etc. It’s great when you can hook it into an issue tracker like Jira or Trac, but Mylyn can work just as well without a formal issue tracker.&lt;/p&gt;  &lt;p&gt;Let’s look at what that actually means.&lt;/p&gt;  &lt;h2&gt;How Mylyn benefits me as a CFML developer&lt;/h2&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Part 1: Noise Reduction through “context”&lt;/h3&gt;  &lt;p&gt;My main Eclipse workspace contains dozens of projects. I keep all projects closed except active projects. Even with only a single open project, the workspace contains hundreds if not thousands of files. Here’s a screenshot of the Project Explorer with me working on an MXUnit issue, with just that project active in my workspace:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/__j-6QTK4wT8/S4mmvniKvpI/AAAAAAAAAQI/0C6pDQZeQEA/s1600-h/mylyn_1%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mylyn_1" border="0" alt="mylyn_1" src="http://lh5.ggpht.com/__j-6QTK4wT8/S4mmwEovdcI/AAAAAAAAAQM/MM1UTtTlMK4/mylyn_1_thumb.png?imgmax=800" width="260" height="170" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As I’m developing, I probably only care about a few files at a time. But the project explorer doesn’t help me keep “just those files” in view. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;This is the first problem Mylyn solves: it helps you keep all the files you care about in sight and hides the rest.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Here’s what that same screen looks like when I create a task for what I’m working on:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/__j-6QTK4wT8/S4mmwjHDKbI/AAAAAAAAAQQ/-dFuPOxquvU/s1600-h/MYLYN_2%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="MYLYN_2" border="0" alt="MYLYN_2" src="http://lh6.ggpht.com/__j-6QTK4wT8/S4mmw399JYI/AAAAAAAAAQU/-Wbxcp4rbSs/MYLYN_2_thumb.png?imgmax=800" width="260" height="170" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Notice how the project explorer now contains just the files I want to see. This is the &lt;strong&gt;context&lt;/strong&gt; of the issue I am working on. As I open more files, they get added to the context. If I want, files can drop off of the context as I close them. Removing files from the context manually is a keyboard shortcut away (ctrl-alt-shift-downarrow).&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Part 2: Context Switching and Context Reconstitution&lt;/h3&gt;  &lt;p&gt;I have no proof of this, but I’d bet that most developers – at least developers in a corporate environment – work on more than one issue at any one time. Perhaps you’re developing a feature, and you get an emergency bug that just has to be fixed right this second or oh my God we’re all gonna die. Perhaps you’re fixing a bug in some system and as you’re doing so, you stumble on a bug in another system that you need to fix first because it’s blocking your ability to fix the immediate bug you’re working on. Regardless of details, this “multi-tasking” appears to be common.&lt;/p&gt;  &lt;p&gt;But I don’t think brains work that way. Brains can’t spawn threads that think about 5 things at once. You can’t be fixing one bug while simultaneously fixing the bug that’s blocking you from your immediate bug fix. We have not acquired such higher consciousness yet.&amp;#160; So no… we don’t multi-task.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;We context-switch. &lt;/strong&gt;Very very fast, in some cases.&lt;/p&gt;  &lt;p&gt;The inevitable problem with context switching is that as soon as you stop working on Thing 1, and move on to Thing 2, the process begins whereby you forget stuff about Thing 1. You forget what code you were working on. You forget what you were thinking. You forget what other files were associated. &lt;em&gt;The mental bonds you had constructed around that Thing begin to decay. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;When you return to working on Thing 1, loading all of that data back into memory takes time. This is why programmers are always complaining to managers about “Stop/Start Time”. It’s why, when a PM fails to fully spec a problem, and the developer ends up working on the same thing 5 different times till it’s done right, that developer gets grumpy.&lt;/p&gt;  &lt;p&gt;Imagine, though, if moving from one issue to another, and back again, was a simple matter of a menu selection.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Imagine:&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;You’re working on Thing 1. You have 8 files associated with it. Your PM comes running down the hall, crying and blathering about how “The client is going to leave us right this very second if we don’t fix (insert dumbass unimportant thing here)!”. &lt;/li&gt;    &lt;li&gt;She enters a bug for Thing 2: “If website font isn’t shrunken by .0003 Pixels, Client will Leave and we’ll all foreclose on our houses”. &lt;/li&gt;    &lt;li&gt;You close all the files you’re working on, you open up the appropriate files for this new bug. You save the day and the houses of your colleagues &lt;/li&gt;    &lt;li&gt;You close those files, hit a button, and presto, you’re back into your original bug… at the same file, perhaps even at the same mouse location. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;That’s context switching. You’ve moved from Thing 1 to Thing 2. When finished with Thing 2, you moved back to Thing 1… right where you left off. You’ve &lt;strong&gt;reconstituted your original context.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;This is the second problem mylyn solves: it helps you move from task to task and back again.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I recently wrote about how I do this context switching with my favorite Mylyn toolbar item, and I &lt;a href="http://blog.mxunit.org/2010/02/best-eclipse-menu-youve-never-heard-of.html" target="_blank"&gt;invite you to read that&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;Part 3: Context Sharing&lt;/h3&gt;  &lt;p&gt;At work in particular, I often work on something and then sometime down the road, I need to work on something similar. If it hasn’t been too long, I’m likely to remember that thing I worked on. I’ll search Jira and find the issue number.&amp;#160; Wouldn’t it be nice if I could take that “context” (remember… for us, Context means basically&amp;#160; “a collection of files”) and copy it to my new Jira issue? With Mylyn, you can do that:&lt;/p&gt;  &lt;p&gt;From the “task” editor for the original task, I go to the Context tab and click “Copy Context to…”. It pops up a task finder, I select or search for the new task, hit a button, and bam, done.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/__j-6QTK4wT8/S4mmxf1HN9I/AAAAAAAAAQY/CO4jhfEpG1w/s1600-h/mylyn_3%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mylyn_3" border="0" alt="mylyn_3" src="http://lh3.ggpht.com/__j-6QTK4wT8/S4mmx9IOCzI/AAAAAAAAAQc/Yra4fnFaG3M/mylyn_3_thumb.png?imgmax=800" width="260" height="170" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now, I deactivate that old task, activate the new one, and this is what it looks like:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/__j-6QTK4wT8/S4mmyTAsIWI/AAAAAAAAAQg/AaJROqE0NZM/s1600-h/mylyn_4%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mylyn_4" border="0" alt="mylyn_4" src="http://lh4.ggpht.com/__j-6QTK4wT8/S4mmy31TO4I/AAAAAAAAAQo/xF80aYwYCvY/mylyn_4_thumb.png?imgmax=800" width="260" height="170" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;That’s right… just like the “source” task, except in a new task. My original task remains untouched, and anything I add or remove from this new one is unique to just this task.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;This is the third problem mylyn solves:&lt;/strong&gt;&amp;#160;&lt;strong&gt;It literally takes seconds to transfer the “mindset” of a previous task to a new task.&lt;/strong&gt;&lt;/p&gt;  &lt;h2&gt;Summary&lt;/h2&gt;  &lt;p&gt;As developers, we are expected to be more and more productive. By default, constant stop/start – constant context switching – is anathema to productivity. Mylyn helps mitigate the pains associated with this kind of chaotic working style, and that’s why it has become one of my most valued and loved tools.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-5534025250080020149?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/02/why-mylyn-is-indispensible.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>8</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-3162468438491008041</guid><pubDate>Tue, 23 Feb 2010 13:18:00 +0000</pubDate><atom:updated>2010-02-23T08:20:07.228-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>eclipse</category><category domain='http://www.blogger.com/atom/ns#'>mylyn</category><category domain='http://www.blogger.com/atom/ns#'>timesavers</category><title>The Best Eclipse Menu You’ve Never Heard Of</title><description>&lt;p&gt;Where I work, a kind of schizophrenia is the norm. It’s rare that I can work on any single Jira issue, from start to finish, without being pulled off of that issue and onto another. It’s also rare for me to have fully defined requirements backing any single issue, and so even when I think I’m finished, I usually need to revisit. What I’m trying to say is that there’s a whole lot of start/stop/resume. It’s not ideal, but it’s how we roll.&lt;/p&gt;  &lt;p&gt;Prior to Mylyn, this was maddening. Mylyn, though, makes it easy to get into, out of, and back into issues at the point where I left off. In earlier versions (I’m thinking around the Eclipse 3.3 timeframe), Mylyn would contribute a toolbar item that made it braindead simple to navigate previous tasks. It is a little purple arrow which looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/__j-6QTK4wT8/S4PVhOXTSvI/AAAAAAAAAO8/RMdarcGbqRw/s1600-h/mylynprevioustask%5B10%5D.png" target="_blank"&gt;&lt;img title="mylynprevioustask" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="328" alt="mylynprevioustask" src="http://lh4.ggpht.com/__j-6QTK4wT8/S4PVhQ_3iGI/AAAAAAAAAPA/Wl2Uxk1tt-w/mylynprevioustask_thumb%5B13%5D.png?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When you want to work on a previously worked-on issue, you simply hit the arrow, pick your previous issue from the list, and you’re back in the context of that issue. It is, no question, my most frequently used toolbar item. &lt;/p&gt;  &lt;p&gt;Around the 3.4 timeframe, it went missing from a fresh Eclipse install. Here’s how to get it back:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Window – Customize Perspective &lt;/li&gt;    &lt;li&gt;Select the “Command Groups Availability” tab &lt;/li&gt;    &lt;li&gt;In the “Available Command Groups” pane, scroll down toward the bottom and find the “Task Navigation Extras” checkbox. Toggle it. Save your windows &lt;/li&gt;    &lt;li&gt;Exult! &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Here’s what the Command Groups tab should look like:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/__j-6QTK4wT8/S4PVh3PFHAI/AAAAAAAAAOs/he9kLbD7mvQ/s1600-h/mylyncommandgroups%5B7%5D.png" target="_blank"&gt;&lt;img title="mylyncommandgroups" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="526" alt="mylyncommandgroups" src="http://lh5.ggpht.com/__j-6QTK4wT8/S4PViehcpcI/AAAAAAAAAOw/Zc8oodnOR50/mylyncommandgroups_thumb%5B7%5D.png?imgmax=800" width="654" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;While you’re poking around the Command Groups, note that you can also deselect stuff that you don’t use, which can aid in noise reduction. Enjoy.&lt;/p&gt;  &lt;p&gt;--marc&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-3162468438491008041?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/02/best-eclipse-menu-youve-never-heard-of.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>6</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-9188574473811753379</guid><pubDate>Fri, 19 Feb 2010 02:50:00 +0000</pubDate><atom:updated>2010-02-22T20:16:12.407-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Best Practices</category><title>Dropdowns: The Scourge</title><description>&lt;p&gt;It doesn’t happen much that I think about HTML. In a weird convergence of events, though, I find myself reflecting on SELECT boxes, aka “dropdowns”. Specifically, how they are my own personal bane, and how application developers can redress the scourge they have put upon us. &lt;/p&gt;  &lt;p&gt;This is my story.&lt;/p&gt;  &lt;h2&gt;Consider&lt;/h2&gt;  &lt;p&gt;This is a screenshot from Mint.com’s account setup screen, wherein you can enter your username, password, and answer security questions for the account which match the security questions from your bank. The typical workflow goes:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;You answer your security questions at your bank’s website &lt;/li&gt;    &lt;li&gt;You go to Mint, you set up the account (account numbers, usernames, blah blah), and you fill in the security questions &lt;/li&gt;    &lt;li&gt;You hit a submit button, magic happens, and all your data gets pulled into Mint. &lt;/li&gt;    &lt;li&gt;Glory ensues &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Except: Step number 2 isn’t really step number 2. It’s like step 2 through 108. With the 106 steps being “read every $*%!ing option in the “security question” dropdown list 5 times, maybe 10, to try to find a match to the questions that you answered on your bank’s site. Oh: they’re not sorted; they’re not worded exactly; they’re in no way thematically related. It. takes. for. ever.&lt;/p&gt;  &lt;p&gt;To wit, pain:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/__j-6QTK4wT8/S35wtw_6r_I/AAAAAAAAAOQ/v4l0i3UBnbo/s1600-h/mintdropdown%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mintdropdown" border="0" alt="mintdropdown" src="http://lh3.ggpht.com/__j-6QTK4wT8/S35wud-DxcI/AAAAAAAAAOU/QQKo8kE8u04/mintdropdown_thumb.png?imgmax=800" width="239" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Notice the size of the thumb on that dropdown. Notice how the questions are ordered in no sensible manner. Imagine using this &lt;strong&gt;for real&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;I dare you to guess how many choices there are in that one option list. Now multiply it by 3, because that’s how many questions you have. By the way, Intuit now owns Mint.&lt;/p&gt;  &lt;h2&gt;And you thought that was bad&lt;/h2&gt;  &lt;p&gt;You will not be able to read the content of this image. You will, however, see that it is an HTML dropdown, based on the fact that there is a scrollbar on the right side. The thumb is a few millimeters tall, indicating that the list is very long.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/__j-6QTK4wT8/S338fnj7uxI/AAAAAAAAAN4/x8dCN-PAS8E/s1600-h/qbdropdown%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="qbdropdown" border="0" alt="qbdropdown" src="http://lh6.ggpht.com/__j-6QTK4wT8/S338gMQYTBI/AAAAAAAAAN8/YAC-idknO6Y/qbdropdown_thumb.png?imgmax=800" width="260" height="128" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This is part of a time-keeping application that folk in my company must use. This dropdown contains a list of projects. You go to this screen, you pick your project, you pick options from other dropdown lists, you enter how many minutes you worked on that application for the day. Repeat as needed.&lt;/p&gt;  &lt;p&gt;Now, I figure that most developers work on at most 5 projects at any one time. Do you know how many projects are in the list in this screenshot? Can you guess? Now, in your head, do the math…&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;5 / &lt;strong&gt;NumAvailableProjects&lt;/strong&gt; = % of shit that is relevant&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;or something like that. It doesn’t matter. Math doesn’t matter. The size of that thumb in the dropdown is all that matters.&lt;/p&gt;  &lt;h2&gt;Your job as a user&lt;/h2&gt;  &lt;p&gt;Your job as a user of an HTML select is to pick an option from a list. &lt;strong&gt;Usually&lt;/strong&gt;, you know &lt;strong&gt;exactly&lt;/strong&gt; what you want. Or damn close. Probably you use this application every day. That means when you’re picking options from your Project list, you know 90% of the characters in the text string that makes up the OPTION. You’re not poking around, thinking “hmmmm, I wonder what options are available to me”. Most option lists you encounter aren’t a whimsical stroll through unknown possibilities (like, for example, “Which shipping method would you like?”). &lt;/p&gt;  &lt;p&gt;Most of the dropdowns in your life contain XX% noise, and 1 thing you want. But you gotta get through the XX%, every single time.&lt;/p&gt;  &lt;p&gt;When I was 15, I took a job as a meat room cleanup kid. I learned how to use a knife, how to clean a block, how to “bone meat”. Eventually, during college, I worked as a meat cutter. I “worked racks”, which meant taking racks of meat from the cooler to the case and back again. Meat rooms are designed for efficiency of meat movement. If it were still alive, a Delmonico could wheel itself from cooler to case… that’s how well most meat rooms are designed.&lt;/p&gt;  &lt;p&gt;Imagine putting a 3-foot curb between the cooler to the meat room, then from the meat room to the supermarket floor. How, tell me, could you wheel that meat cart over a 3-foot curb?&amp;#160; HTML dropdowns like the one above do the same kind of disservice to a user: they significantly impede progress. If you’re a manager-type, you won’t understand anything I’ve written here, so let me put it into Manager-ese: It “has a negative effect on productivity”.&lt;/p&gt;  &lt;p&gt;By the way, that dropdown is courtesy of QuickBase, a wondrous, extensible, powerful, enterprise-y application. Sadly, I know nothing of its wonder. All I know is that I have to pick a single project from that enormous dropdown list and I hate the application for it. By the way, QuickBase is an Intuit application.&lt;/p&gt;  &lt;h2&gt;You need to know&lt;/h2&gt;  &lt;p&gt;Take off your user hat, and put on your developer hat: You need to know that as the application developer, all those fancy things you do to get your enterprisey app to meet all the needs of all your big-dollar customers – to make your app behave as a JeeJaw for Customer1 and a Fahoozle for Customer2 AND a timekeeping application for Me – all the magic you have to work doesn’t mean a damn thing to people like me. What matters to me is the dropdown. I don’t want to marvel at your skill. I want to fill out my timesheet and do my real job. But I can’t do that quickly because I have to pick one option from a 523-and-growing list of projects.&lt;/p&gt;  &lt;p&gt;I know, I know. “But that’s not how we designed it!”&lt;/p&gt;  &lt;p&gt;Whatever. You wrote it. You own the Problem. Only you can fix it.&lt;/p&gt;  &lt;h2&gt;How to fix it&lt;/h2&gt;  &lt;p&gt;The current SELECT element in html is broken. Even 15 years ago, people knew it sucked. Every time you have to choose a date from an old-school date picker (month, day, year), you’re suffering from the failures of the HTML fathers to predict the grievous abuses that website developers would inflict. Every time you fill out your credit card details in an order form and have to scroll through an interminable list of expiration dates, you pay for their mistake. Perhaps you have some authority in your projects to suggest a correction.&lt;/p&gt;  &lt;p&gt;I started with what is, frankly, the only awful part of the Mint.com experience. I’m going to end with the part of the application I interact with most frequently and which I consider the current best model for what SELECT lists should become. In other words, If I were in charge of the HTML spec, dropdown lists would have this functionality &lt;strong&gt;built in&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/__j-6QTK4wT8/S338gcruJrI/AAAAAAAAAOA/xlZMmRHr304/s1600-h/goodmint%5B3%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="goodmint" border="0" alt="goodmint" src="http://lh3.ggpht.com/__j-6QTK4wT8/S338hGz97lI/AAAAAAAAAOE/2Y0UBFt2xLg/goodmint_thumb%5B1%5D.png?imgmax=800" width="449" height="788" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I’m making this image big b/c I want you to see it right away. Notice how the dropdown list itself is a type-in box. It is built for filtering. It’s built for action. Your job as account maintainer is to look at a line item and assign it to a category if Mint.com got it wrong. You know exactly what it needs to be. Or close enough. You know it’s a “coffee”. You know it’s “gas” for your car. You know it’s a tax of some sort. Mint’s category dropdown perfectly addresses this need. You start typing in the type-in box, and it filters down to whatever options might match what you’re searching for. You could have 300 categories and subcategories configured, or you could have 1000. It does not matter. &lt;/p&gt;  &lt;p&gt;This is what that same dropdown looks like as soon as I start&amp;#160; typing the name of the category I want to put the expense in:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/__j-6QTK4wT8/S338hREbiPI/AAAAAAAAAOI/ID4ki4nFawY/s1600-h/mintrocks%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mintrocks" border="0" alt="mintrocks" src="http://lh3.ggpht.com/__j-6QTK4wT8/S338hy3CXLI/AAAAAAAAAOM/-iqczdczB4I/mintrocks_thumb.png?imgmax=800" width="177" height="112" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I do not need to know exactly how the category starts, either. This is critical: good searching lets you, the user, be “close enough”. For example, if I wanted to categorize something as “auto insurance”, but didn’t remember if the category was “car insurance or “auto insurance”, I’d just start typing “Insurance”. With a few characters of typing, it narrows down to the available options, and I can easily see that “Auto Insurance” is what I want. I arrow to the choice I want, hit “enter”, and I’m done.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/__j-6QTK4wT8/S4HNitDKvvI/AAAAAAAAAOY/3IHupvs1Jfs/s1600-h/mintrocks2%5B3%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mintrocks2" border="0" alt="mintrocks2" src="http://lh3.ggpht.com/__j-6QTK4wT8/S4HNi9fGLcI/AAAAAAAAAOc/Zxms19AIWTg/mintrocks2_thumb.png?imgmax=800" width="260" height="140" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The central concept is:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;You know what you’re looking for&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The standard HTML Select list is built around: “&lt;strong&gt;WE&lt;/strong&gt; have no idea what you’re looking for. You choose”.&lt;/p&gt;  &lt;h2&gt;Let me break this down for you&lt;/h2&gt;  &lt;h3&gt;Good&lt;/h3&gt;  &lt;p&gt;“You know”&lt;/p&gt;  &lt;h3&gt;Bad&lt;/h3&gt;  &lt;p&gt;“We don’t know”&lt;/p&gt;  &lt;h2&gt;As a developer, you should…&lt;/h2&gt;  &lt;p&gt;Find ways to anticipate odious dropdowns in your applications. When you find them, consider a Mint.com style dropdown. &lt;/p&gt;  &lt;p&gt;If you have good suggestions for canned/pre-built/jquery plugin/whatever examples of this, please share them with the rest of us.&lt;/p&gt;  &lt;p&gt;Until you do so, realize that every dropdown that is populated by&amp;#160; a database query or some other external, non-hard-coded datasource has the potential to grow. Do not kid yourself thinking “it’ll only ever be a few elements”. It won’t. The thumb will get smaller and smaller, and some user will start to complain. And you know what:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;They’re right.&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-9188574473811753379?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/02/dropdowns-scourge.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>10</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-6054552629323487861</guid><pubDate>Tue, 09 Feb 2010 12:33:00 +0000</pubDate><atom:updated>2010-02-09T07:33:45.500-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>eclipse</category><category domain='http://www.blogger.com/atom/ns#'>coldfusion builder</category><title>Does ColdFusion Builder freeze for you? You can help</title><description>&lt;p&gt;I’ve been using ColdFusion builder extensively at work recently. It is beta software, so my intentions for using it are at least in part to help ferret out bugs so that when it launches, it’s a stable product that we can all trust. Currently, it’s not quite there yet, and so I want to show you a quick and easy tip for helping the CFBuilder team diagnose problems related to stability. This is in the spirit of “every little bit helps”.&lt;/p&gt;  &lt;p&gt;I have posted this bug, which contains a description of what I experience every time CFBuilder freezes/hangs. In addition, I attached a java Stack Trace to the bug, hoping to give the CFB team some insight into what Eclipse is doing at the time of the freeze. I think that seeing the stack trace is about as close as we can get to showing what’s happening under the hood when CFB freezes.&lt;/p&gt;  &lt;p&gt;This assumes you have a recent JDK installed and on your path. You’ll know you’re good if you can open a cmd and type “java –version” and get information. If you can do that, proceed. If not, download a JDK, install it, and continue.&lt;/p&gt;  &lt;p&gt;To get a stack trace, you need to know one thing: the process ID of the javaw.exe process for CFBuilder. In Windows, this is as simple as opening up Task Manager (ctrl-alt-escape), finding javaw.exe, and noting the value in the “PID” Column. If you don’t have that, you can get it by choosing “View – Select Columns” and toggling the “PID” checkbox. It looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/__j-6QTK4wT8/S3FWJhmFUqI/AAAAAAAAANo/9x9iUps21O4/s1600-h/taskmanager%5B2%5D.png" target="_blank"&gt;&lt;img title="taskmanager" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="taskmanager" src="http://lh3.ggpht.com/__j-6QTK4wT8/S3FWKMdp_iI/AAAAAAAAANs/zu6sTS-Hkc4/taskmanager_thumb.png?imgmax=800" width="189" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Now then, to get the stack trace into a file, open a cmd and type &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;jstack &amp;lt;pid&amp;gt; &amp;gt; CFBuilderStackTrace.txt&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This will pipe the output of the jstack command into that file. From there, you can copy the stack. Feel Free to add it as a comment to &lt;a href="http://cfbugs.adobe.com/bugreport/flexbugui/cfbugtracker/main.html#bugId=82019" target="_blank"&gt;this bug&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;--marc&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-6054552629323487861?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/02/does-coldfusion-builder-freeze-for-you.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>6</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-4136911314943884580</guid><pubDate>Tue, 09 Feb 2010 10:00:00 +0000</pubDate><atom:updated>2010-02-09T05:39:14.942-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>coldfusion</category><category domain='http://www.blogger.com/atom/ns#'>CFUnited</category><title>CFUnited 2010: Two Topics You Do Not Want To Miss</title><description>&lt;p&gt;OK, OK, I know. I normally don’t truck with such dramatics, but the two topics I want to talk about merit it.&lt;/p&gt;  &lt;p&gt;I’m talking, of course, about the two topics I submitted this year to CFUnited 2010. I’m asking for the chance to earn your vote. If you want to skip my stump speech, simply&lt;/p&gt;  &lt;h2&gt;&lt;a href="http://callforspeakers.cfconf.org/?event=vote&amp;amp;eventId=188" target="_blank"&gt;Go here and Vote&lt;/a&gt;&lt;/h2&gt;  &lt;p&gt;You click that link, you search for “Esher”, you click the checkbox beside it, and you fill out a little more info and submit the form. I cannot emphasize enough how much good you will be doing for this world of ours (if you don’t, the terrorists have won. Do you want that on your conscience? Didn’t think so). Vote for change you can believe in!&lt;/p&gt;  &lt;h2&gt;My Pitch&lt;/h2&gt;  &lt;h3&gt;Session #1: Debugging like a Rock Star&lt;/h3&gt;  &lt;p&gt;Last year at CFUnited, I presented on “Automating like a Rock Star”, wherein I spoke on batch processing, keyboard launchers, ANT, and JMeter. I covered a wide range of subjects, all with an eye towards helping make your development life less monotonous and more enjoyable.&lt;/p&gt;  &lt;p&gt;This year, I’d like to present with that same goal in mind: helping bring more joy to your day job. I know: there sometimes is nothing more joy-less than debugging. I don’t pretend to have magic pixie dust that you can sprinkle on your apps to make all your nightmares vanish. But I do have a bunch of strategies that have served me well. We’ll cover the most basic CF debugging – how to read a stack trace / tagcontext, how to trace through an object graph, etc – and move on to tricks for what is potentially the hardest debugging: when your app manifests bugs in production that didn’t appear during development.&lt;/p&gt;  &lt;p&gt;Rock Stars don’t fill arenas by growing long hair and putting on makeup and pursing their lips (except Poison, but they rocked, so…). Rather, they work hard, practice till their fingers&amp;#160; and noses bleed, and out-persist lesser musicians. This session aims to demonstrate how to out-persist your bugs.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Session #2: End-to-end Testing Roundtable&lt;/h3&gt;  &lt;p&gt;How many sessions have you been to at a conference where you sat in a chair, a dude like me walked up on stage, said who he is, and rattled on for 50 minutes? &lt;/p&gt;  &lt;p&gt;The End-to-End testing roundtable is NOT that session.&lt;/p&gt;  &lt;p&gt;This session will be “facilitated” by some of my best friends in the community. We have no idea whether this will work. It could be the most boring hour or two of your life. But man… it could be awesome! What we hope for is that we can harness the collective experience in the room to discuss wins, failures, challenges, ah-ha’s, and other manner of discoveries related to application testing. We’ll talk a little bit about the different kinds of testing (unit, integration, the blurry lines), and from there, it’s all about engaging the audience. &lt;/p&gt;  &lt;p&gt;We have no slidedeck backup. We have no prepared demos. All we have is a hope that we can attract a room of people who want to teach and learn.&lt;/p&gt;  &lt;p&gt;If this sounds interesting to you, we simply say, “&lt;a href="http://blogs.hbr.org/haque/2009/12/the_builders_manifesto.html" target="_blank"&gt;Come&lt;/a&gt;”.&lt;/p&gt;  &lt;h2&gt;Sessions you can believe in&lt;/h2&gt;  &lt;p&gt;Look: if you have worked with people, or are one of those people, who struggle constantly with effective, productive debugging, then I’m asking&amp;#160; you to check the checkbox for Debugging like a Rock Star.&lt;/p&gt;  &lt;p&gt;If you want to take part in – or at least give others this opportunity to participate in – a one-of-a-kind session on application testing, then please check the checkbox for the End to end testing roundtable.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://callforspeakers.cfconf.org/?event=vote&amp;amp;eventId=188" target="_blank"&gt;Go here and Vote&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Thank you. And God Bless America.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-4136911314943884580?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/02/cfunited-2010-two-topics-you-do-not.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-2585398637830426194</guid><pubDate>Sun, 31 Jan 2010 03:16:00 +0000</pubDate><atom:updated>2010-01-31T14:18:17.521-05:00</atom:updated><title>Dissecting The Bug</title><description>&lt;h2&gt;Shifting gears&lt;/h2&gt;&lt;div style="float: right;"&gt;&lt;img alt="" height="312" src="http://i905.photobucket.com/albums/ac259/virtix/gears.jpg" width="320" /&gt;&lt;/div&gt;Attending school forces me into a different mind-set, requiring me to slow down and really think hard about abstract concepts, rather than just fixing bugs as quickly as possible. I like this. It’s also very inspiring to sit in class and listen. It’s been a while and I’ve forgotten, but it’s kind of like being in a conference session without the glitz and knowing it’s going on for several hours, days, and months, vs. a mere 50 minutes.  I was impressed, too, by my professor, Paul Ammann, who’s incredibly smart, skilled, and understands the practical needs of technology. This is key—having professors who don’t acknowledge what practitioners &lt;i&gt;have&lt;/i&gt; to do to stay employed shows a lack of understanding. Paul, on the other hand, demonstrates a keen grasp of this important concept. Many students, myself included, enjoy abstraction, see value in it, but also need to apply concrete concepts in order to put food on the table and clothes on the kids. Case in point, almost to the minute my job agreed to pay for this class, I got a new project: “Bill, we want you to automate the testing for Project &lt;span class="caps"&gt;XYZ&lt;/span&gt;, our highest priority project”.  Little do they know that this course is &lt;i&gt;not&lt;/i&gt; about automating testing—it’s about good test design, which, of course, is fundamental to any good quality assurance efforts.&lt;br /&gt;
&lt;br /&gt;
Ok, enough about me …&lt;br /&gt;
&lt;br /&gt;
So, in the most recent class (#2), we discussed a single software fault in painstaking detail. It was dissection, the main concepts being _observability_ and it's antithesis.&amp;nbsp; These are my notes, some reflection, practice, a little poetic license, and likely a mistake or two.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: right;"&gt;&lt;img alt="" height="108" src="http://i905.photobucket.com/albums/ac259/virtix/rip.jpg" width="200" /&gt;&lt;/div&gt;&lt;b&gt;&lt;span class="caps"&gt;RIP&lt;/span&gt; Observability Model&lt;/b&gt;&lt;i&gt; &lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
This model articulates three abstract properties that must exist in a program execution in order for a software fault to be observable.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Reachability&lt;/b&gt; – the fault in the code has to be reachable&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Infection&lt;/b&gt; – the fault has to put the program into an error state. This does &lt;i&gt;not&lt;/i&gt; necessarily mean the program will return incorrect results—this is an important distinction! Just because a program is in an error state does not mean that it will &lt;i&gt;always&lt;/i&gt; produce the wrong result. &lt;i&gt;see below&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Propagation&lt;/b&gt; – the program needs to exhibit incorrect behavior; e.g., incorrect outputs or behavior or throwing an unspecified exception&lt;/li&gt;
&lt;/ul&gt;A program can exhibit zero, one, or two of these properties, but in order for it to be &lt;i&gt;observable&lt;/i&gt; &lt;b&gt;all&lt;/b&gt; these criteria need to be met.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Dissection&lt;/h3&gt;&lt;br /&gt;
This code looks simple, and it is, but using  simple code helps in grasping the &lt;span class="caps"&gt;RIP&lt;/span&gt; concepts.  This is not the same code we covered in class, but it is in &lt;a href="http://books.google.com/books?id=leokXF8pLY0C&amp;amp;dq=introduction+to+software+testing&amp;amp;printsec=frontcover&amp;amp;source=bn&amp;amp;hl=en&amp;amp;ei=WVFjS-SfK8PklAehjYm0Aw&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;ct=result&amp;amp;resnum=4&amp;amp;ved=0CBsQ6AEwAw#v=onepage&amp;amp;q=&amp;amp;f=false"&gt;the book&lt;/a&gt;. The code has a bug; try to find it …&lt;br /&gt;
&lt;pre class="brush: java;"&gt;/**
*
* Effects: returns the index of the last element that matches y, else returns -1
*
* @returns int
* @throws NullPointerException
*/
public int lastIndexOf(int[] x, int y) {

  for (int i = x.length-1; i &amp;gt; 0; i--){
   if( x[i]==y ) return i;
  }
  
 return -1;
}
&lt;/pre&gt;A typical JUnit test for this would look something like following and the test fails, but why?&lt;br /&gt;
&lt;pre class="brush: java;"&gt;@Test
public void testLastIndexOf(){
   int expected = 0;
   int[] x = {2, 3, 4, 5};
   int y = 2;
   int actual = theClass.lastIndexOf(x,y);
  Assert.assertEquals( expected, actual );
  }
&lt;/pre&gt;&lt;br /&gt;
The bug isn't too hard to find simply by looking closely at the code. But if this were buried in some stacktrace it would be much harder to locate—here we already know where it is, within a few lines of code. In the real world, we would simple change the &lt;code&gt;&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;gt;=&lt;/code&gt;, pat ourselves on the back for swatting the fly, and go grab some Fritoes.  But with a slightly more rigorous approach, we have an opportunity to explore some interesting and useful concepts—&lt;i&gt;state&lt;/i&gt; and what makes this particular defect observable or not. To be clear, the fault in the code above is the usage of the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;'&amp;gt;'&lt;/span&gt; operator.&lt;br /&gt;
&lt;br /&gt;
The &lt;span class="caps"&gt;RIP&lt;/span&gt; model states that in order for the fault to be observable, it needs to satisfy all three criteria—Reachability, Infection, and Propagation. It’s also helpful to show cases (test cases) where the fault is &lt;i&gt;not&lt;/i&gt; observable, yet puts the program in an error state. How can a program be in an error state and not output an error? These are the kinds of bugs many of us have wrestled with—the kind of bug that gnashes its sharp mandibles only under certain circumstances.&lt;br /&gt;
&lt;br /&gt;
&lt;table&gt;&lt;tbody&gt;
&lt;tr&gt;   &lt;td&gt;The questions to ask are (and these are loosely taken from &lt;a href="http://books.google.com/books?id=leokXF8pLY0C&amp;amp;dq=introduction+to+software+testing&amp;amp;printsec=frontcover&amp;amp;source=bn&amp;amp;hl=en&amp;amp;ei=WVFjS-SfK8PklAehjYm0Aw&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;ct=result&amp;amp;resnum=4&amp;amp;ved=0CBsQ6AEwAw#v=onepage&amp;amp;q=&amp;amp;f=false"&gt;the book&lt;/a&gt;) :&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;in which case(s) would the fault &lt;i&gt;not&lt;/i&gt; execute?&lt;/li&gt;
&lt;li&gt;in which case(s) would the fault execute yet &lt;i&gt;not&lt;/i&gt; create an error state?&lt;/li&gt;
&lt;li&gt;in which case(s) would the fault execute and create an error state, but not propagate?&lt;/li&gt;
&lt;li&gt;in which case(s) would the inputs cause execution of the of the fault, cause an error state, and propagate? &lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;/td&gt;   &lt;td&gt;&lt;img alt="" src="http://i905.photobucket.com/albums/ac259/virtix/Brain_1.jpg" /&gt; &lt;/td&gt;  &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;
If you're still reading my guess is that you want to know how you can execute a fault, be in an error state, yet not propagate. The other questions can be figured out without too much problem, but this one, might cramp the brain a bit.&amp;nbsp; First, let's define what state is.&amp;nbsp; State can be defined as a combination of variable and value pairs plus the program counter (PC) — this is where the code &lt;i&gt;should be&lt;/i&gt; executing. It can also be viewed as a snapshot of the data plus the location of the program's execution pointer. Example: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
S &lt;sub&gt;0&lt;/sub&gt; → S &lt;sub&gt;1&lt;/sub&gt; → S &lt;sub&gt;2&lt;/sub&gt; → S &lt;sub&gt;3&lt;/sub&gt;  → S &lt;sub&gt;4&lt;/sub&gt;  → S &lt;sub&gt;5 , &lt;span style="font-size: small;"&gt;where &lt;/span&gt;&lt;/sub&gt;S &lt;i&gt;n&lt;/i&gt;&lt;sub&gt;&lt;span style="font-size: small;"&gt; represents some state of execution within the program.&lt;/span&gt;&lt;/sub&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
But, sometimes the program &lt;i&gt;skips&lt;/i&gt; a state and goes from S &lt;sub&gt;3&lt;/sub&gt;  → S &lt;sub&gt;5. &lt;span style="font-size: small;"&gt;This is the &lt;i&gt;error state&lt;/i&gt;. If a some code is supposed to execute some line and it does not, that's skipping an intended state, which is bad.&lt;/span&gt;&lt;/sub&gt;&lt;br /&gt;
&lt;br /&gt;
In S &lt;sub&gt;0&lt;/sub&gt; we’re entering the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;lastIndexOf(...)&lt;/span&gt; method and we have values for inputs &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;x&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;y&lt;/span&gt;. In S &lt;sub&gt;1&lt;/sub&gt; we’re now at &lt;code&gt;for(int i = x.length-1; ...)&lt;/code&gt; and our state now has some value for &lt;code&gt;i&lt;/code&gt;. What if we have a single element array; e.g., &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;x = [ 1 ]&lt;/span&gt; instead? Because it’s only one element, this gives &lt;code&gt;i&lt;/code&gt; the value of 0, so the bug &lt;code&gt;i &amp;gt; 0&lt;/code&gt; kicks us out of the for loop, pushes us down to the return statement, and then returns the correct result, -1. The &lt;b&gt;error state&lt;/b&gt;—and this is the take-home—is the fact the PC &lt;i&gt;never&lt;/i&gt; reaches the &lt;code&gt;if( x[i] == y )&lt;/code&gt; statement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An analysis of the state of the program when the error state was entered can be presented like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Expected State         Actual State
------------------------------------------------------------------------------------
 x = [ 1 ]             x = [ 1 ]    
 y = 2                 y  = 2
 i = 0                 i = 0     
 PC =  if( x[i]==y )   PC = return -1;  &amp;lt;-- &lt;i&gt;error state&lt;/i&gt;&lt;/pre&gt;&lt;br /&gt;
In more concrete terms, this is just saying the code didn’t do what it was supposed to, because it never evaluated the conditional expression &lt;code&gt;if ( x[i]==y )&lt;/code&gt;. In RIP terms this is saying that Reachability was satisfied, Infection was also satisfied (an error state occurred), but Propagation did not occur. So, given the inputs, this software fault is not observable. Again, this is the kind of bug that, usually buried deep in some system, causes us pain. It's very difficult to find after the fact, but a simple unit test up front would catch it.&lt;br /&gt;
&lt;br /&gt;
Today, one test I would write would be make sure that the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;y&lt;/span&gt; was present in every possible index of the array being searched:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Testcases:
x = [2,3,4,5]
x = [3,2,4,5]
x = [3,4,2,5]
x = [3,4,5,2]
&lt;/pre&gt;&lt;br /&gt;
Some array shifting algorithm would be useful here to make test case inputs easier to generate!&lt;br /&gt;
&lt;br /&gt;
Chances are, in practice, you would never go into this much detail about such a small fault. This is taking an opportunity to think about bugs, or software faults, in detailed and abstract terms, which is not only a great exercise, but, it's also a useful and practical way to reason about the complexities of building quality into software. We're not constrained by a particular language implementation, or platform, and dealing with abstractions such as this transcends much of the industry noise and helps us to focus on the principals of software quality, rather than the software itself.&lt;br /&gt;
&lt;br /&gt;
Next up: &lt;b&gt;Coverage Criteria&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Test and Be Happy!&lt;br /&gt;
&lt;br /&gt;
bill shelton&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-2585398637830426194?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/01/dissecting-bug.html</link><author>noreply@blogger.com (bill shelton)</author><thr:total>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-8166047296307668514</guid><pubDate>Mon, 18 Jan 2010 14:26:00 +0000</pubDate><atom:updated>2010-01-30T22:20:47.135-05:00</atom:updated><title>Software Testing</title><description>&lt;h2&gt;I “am” plugging &lt;a href="http://books.google.com/books?id=leokXF8pLY0C&amp;amp;dq=software+testing+book+paul+ammann&amp;amp;printsec=frontcover&amp;amp;source=bn&amp;amp;hl=en&amp;amp;ei=4KFZS9HrDceM8Aas6oz9BA&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;ct=result&amp;amp;resnum=5&amp;amp;ved=0CBkQ6AEwBA#v=onepage&amp;amp;q=software%20testing%20book%20paul%20ammann&amp;amp;f=false"&gt;this book&lt;/a&gt;, and for good reason …&lt;/h2&gt;&lt;span style="font-size: small; font-weight: normal;"&gt;&lt;br /&gt;
&lt;i&gt;Update (January 22, 2010) &lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;: The authors (Paul Ammann and Jeff Offutt) donate 100% of the book's royalties to the &lt;/span&gt;&lt;a href="http://volgenau.gmu.edu/corporate_community_partners/introduction_to_giving.php"&gt;&lt;span style="font-family: inherit; font-size: small;"&gt;Software Engineering Scholarship Fund&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;"&gt;, a scholarship fund for software engineering students.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: small;"&gt;&amp;nbsp;&lt;/span&gt; &lt;br /&gt;
&lt;div style="float: left; padding: 1.5em;"&gt;&lt;a href="http://www.amazon.com/Introduction-Software-Testing-Paul-Ammann/dp/0521880386/ref=dp_return_1?ie=UTF8&amp;amp;n=283155&amp;amp;s=books"&gt;&lt;img alt="" src="http://i905.photobucket.com/albums/ac259/virtix/intro_testing_cover.jpg" /&gt;&lt;/a&gt;  &lt;/div&gt;Admittedly, I am a bit biased, being both a student of the authors and a QA geek. To create even further bias, even though I bought a copy of the book for over a year ago, I never thoroughly read the preface until yesterday. I was both surprised and flattered to read my name in print, acknowledged as one of the students who contributed and helped with the book. I recall reading and commenting on the text before it was published and then being disappointed that I couldn’t attend the class before I graduated—it was a new course then and I had some graduation requirements to fulfill.&lt;br /&gt;
&lt;br /&gt;
Coming from someone who contributes to the core MXUnit test framework, written a few blog posts, and spoken at conferences on testing and TDD, the book’s title may be construed as misleading. It &lt;i&gt;can&lt;/i&gt; be used as an introductory text, but also presents practical, novel, and advanced concepts, such as coverage criteria (graph and logic coverage, input space partitioning, and syntax-based testing ). I suspect one of the main reason’s for the title is to make it accessible at many levels—and this is a big asset. &lt;i&gt;Introduction to Software Testing&lt;/i&gt; can be used both as a text and as a test engineer or developer’s reference.&lt;br /&gt;
&lt;br /&gt;
One of the goals of the book is to strike a balance between theory and practice. The book’s introduction establishes the context of testing in software engineering from a more formal process point of view. (It might be helpful or more accessible if the book were to also mention Agile methods, too, in which testing &lt;i&gt;is&lt;/i&gt; an integral part of the process.) The book also identifies the fundamental weakness we all have to deal with in respect to testing—&lt;i&gt;Testing can show the presence of failures, not their absence&lt;/i&gt;. This key point applies to both manual and automated testing and at all levels, unit through acceptance. In other words, based on your tests, you can’t prove that that your code does &lt;b&gt;not&lt;/b&gt; have bugs. This is one of the main problems the book addresses through exploration of coverage criteria. Through coverage criteria, is it possible to describe and possibly measure the relative quality of your application? …&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: right;"&gt;&lt;img alt="" src="http://blog.billshelton.me/images/back_to_school.jpg" /&gt;&lt;/div&gt;Now some 4+ years after receiving a masters, I’m going back to school and the first class I’m taking is &lt;a href="http://cs.gmu.edu/%7Epammann/637.html"&gt;SWE-637&lt;/a&gt;, &lt;i&gt;Software Testing&lt;/i&gt;, the class I missed on the first go-around. I’m excited to dig deep, however, having a full-time job and being a parent drives me to try to work as smart as possible (that’s a constant learning process). Adding a graduate software engineering program to that, makes for very little time for anything other than that which absolutely necessary. With that, my goal for this semester is to focus on &lt;i&gt;automated test design&lt;/i&gt;—how best to design automated tests in order to cover as many requirement criteria as possible in the least amount of space and time. I’d like to use functional testing as the primary medium and (as a bonus) develop a good grasp of the upcoming 2.0 version of Selenium (with Webdriver) as the test harness. But the focus will be on the principals of good test design rather than the tools.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Coverage criteria&lt;/i&gt; and test design is largely what the course and the book address. After focusing on TDD, unit testing, and building a testing tool, I still have the unanswered question of “what makes a test a good test?”. And how can I measure how much of a class, component, system, object, etc., is &lt;i&gt;adequately&lt;/i&gt; covered by my tests? I know that when I write a lot of tests and take the time to reason about what I’m doing, I know the quality of my software is better. I know, too, coverage tools can let me know what parts of my code have not been exercised. Yet still, there’s that lingering question that tests can’t show the absence of defects …&lt;br /&gt;
&lt;br /&gt;
Test and be Happy!&lt;br /&gt;
&lt;br /&gt;
bill shelton&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-8166047296307668514?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/01/software-testing.html</link><author>noreply@blogger.com (bill shelton)</author><thr:total>3</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-911887353690687474</guid><pubDate>Mon, 11 Jan 2010 10:05:00 +0000</pubDate><atom:updated>2010-01-11T07:23:56.265-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>coldfusion</category><category domain='http://www.blogger.com/atom/ns#'>eclipse</category><category domain='http://www.blogger.com/atom/ns#'>debugging</category><category domain='http://www.blogger.com/atom/ns#'>timesavers</category><title>Using Eclipse MAT to track down a ColdFusion server Out-of-Memory Error</title><description>&lt;blockquote&gt;   &lt;p&gt;Recently, this came across my desk:&amp;#160; “This process is causing ColdFusion to crash on the DEV server. It hasn’t crashed the developer’s local machine. Can you take a look?”&lt;/p&gt;    &lt;p&gt;In this post, I’ll show how I came to the answer in this specific case. I’m putting this out there because the solution was both surprising and simple. I’m also writing about it because I want to show how I came to the answer very quickly, rather than spending hours going down a bunch of dark alleys.&lt;/p&gt;    &lt;h2&gt;The Short Answer&lt;/h2&gt;    &lt;p&gt;For the impatient, or the people who got here from Google, here’s the conclusion: ColdFusion Server Monitor can, indeed, cause your memory to spike, and crash your server, with “Profiling” turned on. It’s common knowledge that keeping the “Memory Tracking” turned on can crash CF; however, it’s rare that you hear about “Profiling” causing troubles.&amp;#160; In my case, I believe the reason was setting the Database “Slowest Queries” and “Most Frequently Run” Queries to be very aggressive. For Slowest Queries, I had it set to give me the last couple hundred queries of 0 seconds. For Most Frequently run, I changed the default from 20 to at least 100.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;To solve the server crash, I simply turned Profiling off.&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;h2&gt;The Journey&lt;/h2&gt;    &lt;p&gt;For those interested in seeing how I concluded Profiling (or, rather, my aggressive settings) was to blame, read on.&lt;/p&gt;    &lt;h3&gt;The Usual Suspects&lt;/h3&gt;    &lt;p&gt;I started by checking the usual OutOfMemory culprits:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Debugging on? &lt;/li&gt;      &lt;li&gt;Memory Monitoring on? &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;Nope.&lt;/p&gt;    &lt;p&gt;I went to server monitor and looked at the database stats: it confirmed my gut reaction, which was that the process was running thousands of queries. This isn’t necessarily a server killer in and of itself, but in my experience, OutOfMemory problems usually lead back to database access. So I went to the source code and checked out the queries that server monitor indicated were frequently run queries. I was looking for the tell-tale server killer: a couple of queries in a loop, and the loop having the possibility of running dozens of thousands of times. What I saw was perhaps questionable, but nothing shocking or easily identifiable as the offender. So, I put this in the back of my head and went to the next step in my process: get a heap dump.&lt;/p&gt;    &lt;p&gt;By now, I’m about 10 minutes into the investigation. The 2 most obvious suspects weren’t implicated, and the 3rd most obvious was suspicious but not definitive. Now, at this point, JRun was up over 1GB of RAM, so a heap dump and parsing the dump would take a long time.&lt;/p&gt;    &lt;h3&gt;Getting a Heap Dump&lt;/h3&gt;    &lt;p&gt;I RDP’d into the dev server, using “mstsc /admin”. You might need to use /console instead. In my experience, using jmap over RDP usually requires one of these options.&lt;/p&gt;    &lt;p&gt;I always have a JDK on the CF Server, so these instructions assume you either have a JDK installed or can &lt;a href="http://java.sun.com/javase/downloads/index.jsp" target="_blank"&gt;install one&lt;/a&gt;.&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Open a cmd, and type: jmap –dump:format=b,file=c:\jrun4\heapdump.bin &amp;lt;pid&amp;gt;, where pid is the windows Process ID of jrun.exe &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;this will put a heap dump file at c:\jrun4\heapdump.bin. If you want it somewhere else, just change the file param to the jmap command.&amp;#160; Now, we need something to parse this file and show us what’s sucking up all the memory.&lt;/p&gt;    &lt;h3&gt;Analyzing a Heap Dump with Eclipse MAT&lt;/h3&gt;    &lt;p&gt;Before I describe the few steps I took, I want to point out Brian Ghidinelli’s excellent &lt;a href="http://www.ghidinelli.com/2009/07/16/finding-memory-leaks-coldfusion-jvm" target="_blank"&gt;set of posts&lt;/a&gt; on &lt;a href="http://www.ghidinelli.com/2009/08/25/my-memory-leak-in-pictures" target="_blank"&gt;analyzing memory problems&lt;/a&gt; in ColdFusion. My post is meant to be&amp;#160; a quick and dirty description of how I found an answer to a memory problem quickly using Eclipse MAT. Brian’s articles are exhaustive, and I strongly encourage you to check them out if you want to *really* learn how to do this stuff.&lt;/p&gt;    &lt;p&gt;Now then: I opened the MAT perspective in Eclipse (this is on 3.5), and I Opened the heapdump.bin file that jmap spit out. It spun for quite some time, and then I got an Out Of Memory error in Eclipse. Ironic, eh? This one was easy to identify, since I was running Eclipse with only 512MB of RAM, and the file I was parsing was over a gig. So I set Eclipse to run with 1350MB of ram by using the-Xmx option in eclipse.ini, and tried to open the file again. This time, it got pretty far, gave an error, but it still had generated some data. It didn’t give the full information one would need for an exhaustive analysis, but it gave me enough. Had I needed more information, I would’ve followed Brian’s instructions in this post for using Eclipse MAT to &lt;a href="http://www.ghidinelli.com/2009/07/30/large-heap-dumps-eclipse-mat" target="_blank"&gt;parse very large files&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;Once I had some information on screen, I clicked the “Dominator Tree” link, and this is what I saw:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh6.ggpht.com/__j-6QTK4wT8/S0jRe7tubRI/AAAAAAAAANg/3SmljjjuD_g/s1600-h/bigheap%5B2%5D.png" target="_blank"&gt;&lt;img title="bigheap" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="179" alt="bigheap" src="http://lh5.ggpht.com/__j-6QTK4wT8/S0jRfB-M3qI/AAAAAAAAANk/32OritK3-3Q/bigheap_thumb.png?imgmax=800" width="303" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;Go ahead. Open that file. Do you see that line at the top… the one with 22 million instances of a single class name consuming almost 1GB of Memory? Yeah… that’s the problem. His name is coldfusion.monitor.stack.CFStackFrame, and &lt;a href="http://www.urbandictionary.com/define.php?term=I%27m%20your%20huckleberry" target="_blank"&gt;he was my huckleberry&lt;/a&gt;. &lt;/p&gt;    &lt;p&gt;At this point in my investigation, I do not know exactly what that class is, but judging by its name, I’m pretty sure it’s related to the CF server monitor. I open server monitor, turn off just the “Monitoring” option, and re-run the application. It crashes within minutes.&lt;/p&gt;    &lt;p&gt;I restart CF, open server monitor, and turn Profiling off. I re-run the application, and it successfully completes. I then turn Monitoring back on – to be sure that it’s isolated to Profiling – and re-run the application. It completes.&lt;/p&gt;    &lt;h3&gt;If there’s a lesson, it’s:&lt;/h3&gt;    &lt;p&gt;After you spend a few minutes investigating and ruling out the usual suspects, stop speculating. Obtain data, and let it guide you. &lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-911887353690687474?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/01/using-eclipse-mat-to-track-down.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-8998442753165755918</guid><pubDate>Thu, 07 Jan 2010 12:27:00 +0000</pubDate><atom:updated>2010-02-22T20:56:39.257-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>coldfusion</category><category domain='http://www.blogger.com/atom/ns#'>closures</category><title>What would your CFML look like with closures?</title><description>&lt;p&gt;In this article, I’ll describe my exploration of closures: what they are, why programmers love them so darn much, and what your CFML code might look like if they were to be introduced into the language. A paragraph worth of disclaimers wherein I basically admit “I don’t know what I’m talking about” will follow. But I figured that was no way to pull you in, so… without further adieu, let’s start. &lt;/p&gt;  &lt;h2&gt;The Problem&lt;/h2&gt;  &lt;p&gt;I’m learning that most advances in one’s thinking start with a problem. This should be common-sense. It’s not like we sit in our chairs all day thinking “I wonder if I can come up with a nifty solution to something today.” Rather, we have problems to solve, we think about the existing solutions, and every once in a while, we realize that what we currently &lt;strong&gt;can&lt;/strong&gt; do isn’t what we &lt;strong&gt;should&lt;/strong&gt; do. Sometimes, the solution hasn’t been born yet. This originality is rare and I’ll leave it to &lt;a href="http://en.wikipedia.org/wiki/Rich_Hickey" target="_blank"&gt;really&lt;/a&gt;, &lt;a href="http://broadcast.oreilly.com/2009/03/an-interview-with-anders-hejls.html" target="_blank"&gt;really&lt;/a&gt;,&lt;a href="http://en.wikipedia.org/wiki/Martin_Odersky" target="_blank"&gt; really smart people&lt;/a&gt;. Often, the currently-unavailable solution has already been born, just in other contexts. In my case, the problem I was trying to solve would have been neatly handled if CFML had closures, which I knew about from various other languages. So let’s talk about the problem, and why closures are a nice way to approach it. I apologize in advance if this specific problem seems confusing. I thought about drumming up a fake problem for sake of clarity, but I decided against that. Real-world problems, though harder to initially grok, have always helped me more fully understand things, even if it takes two reads. &lt;/p&gt;  &lt;p&gt;I have a “&lt;strong&gt;Formatter&lt;/strong&gt;” component. It’s a utility component that does some all-purpose formatting of financial data. Dollars, percents, that sort of junk. This is CF, not Java, and as such we’re not in the business of passing around “Money” objects when a simple decimal value will do. Consequently, it’s useful to be able to pass these values through a Formatter object for display purposes (think: barcharts, tabular data, etc) while still retaining their raw value for use in calculations and whatnot.&lt;/p&gt;  &lt;p&gt;I have a “&lt;strong&gt;TableBuilder&lt;/strong&gt;” component. Its purpose is to take arrays of raw data in an “&lt;strong&gt;addTableRow&lt;/strong&gt;” function and turn them into tables for display. This builder accepts various formatting options, the raw data (one row at a time), and can when requested add additional rows/columns based on the raw data (doing other calculations, etc) as a convenience. When it prints the raw data, it uses the &lt;strong&gt;Formatter&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I have a “&lt;strong&gt;ThingThatUsesTableBuilder&lt;/strong&gt;” component. This component’s job is to build a part of a PDF document. It does all manner of boring things – put some text here, put some text there, add some junk here, draw a box there – and also it needs to plop a table smack dab in the middle. It will use the &lt;strong&gt;TableBuilder&lt;/strong&gt; for that purpose.&lt;/p&gt;  &lt;p&gt;So: ThingThatUsesTableBuilder –&amp;gt;uses TableBuilder—&amp;gt;uses Formatter&lt;/p&gt;  &lt;p&gt;When this TableBuilder was conceived, it was only ever meant to display integer values. As in, if it received decimal values, it rounded them. It was a “Very Bad Thing”(tm) if decimals ever displayed in these tables. Litigation, torture, foreclosure, you name it. Consequently, we built that behavior into this thing. “If you are a decimal, ye shall be smoted into an int”.&lt;/p&gt;  &lt;p&gt;Queue the &lt;a href="http://www.teemorris.com/billipodcast/" target="_blank"&gt;old timey Detective music&lt;/a&gt;. And then “She” came along.&amp;#160; &lt;/p&gt;  &lt;p&gt;You know how it is. You nail down the specs. You argue incessantly about “will we ever need this to be more flexible?” “&lt;a href="http://www.clicknotes.com/macbeth/T34.html" target="_blank"&gt;Avaunt! and quit my sight!&lt;/a&gt;”&amp;#160; And so it goes. You build it to spec, and then down the road, things change. And you end up in my shoes:&lt;/p&gt;  &lt;p&gt;“Marc, what we really need, for this one table, for this one client, for just the first row, is that the decimals should appear. And here’s all the behavior around decimals”. When you’re dealing with Other People’s Money(tm), this stuff can get tricky.&lt;/p&gt;  &lt;p&gt;Fortunately, this formatting business can all be nicely tucked away into the Formatter object and your calculation “engine” (engine means “a thing with a shitload of ‘if’ statements) can remain blissfully unaware of the unwholesome demands being placed upon its sanctity. Unfortunately, the TableBuilder looks like this:&lt;/p&gt;  &lt;p&gt;drawTextFromMacro(textMacroName, formatter.formatWholeDollar(data[col],true,false), startX, startY, startAmountRightX);&lt;/p&gt;  &lt;p&gt;See what it’s doing? Except in this one case, we don’t want that. In this one case, we want something different… we want a decimal amount in the cell, for one call to &lt;strong&gt;addTableRow(), in a TableBuilder whose reason for being is to print whole dollars&lt;/strong&gt;.&lt;/p&gt;  &lt;h2&gt;Existing Solutions&lt;/h2&gt;  &lt;p&gt;Myriad approaches exist.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Change the TableBuilder to not expect the data to be raw, but to instead expect the data to be formatted. This is perhaps acceptable if the TableBuilder didn’t also want to perform additional calculations on the incoming data. And so if we make this change, we must also change the input data to have those calcs done ahead of time. Small inconvenience, perhaps, but it does start to make the method signatures on this component get really hairy &lt;/li&gt;    &lt;li&gt;Accept a formatter object as an arg to the function that does the drawing. This would work, too, since CF enables dynamic method calls via CFINVOKE. But in order to do this, I’d need to pass the formatter object, the function to be called, and the arguments to that function. So now my method signature just ballooned by 3. Blech. &lt;/li&gt;    &lt;li&gt;Stop being lame with this “Formatter” object business, and create a different formatter for all the possible conditions I might encounter: WholeDollarFormatter, DecimalFormatter, PercentFormatter, and on and on. Then, I just construct an appropriate instance inside my loop that’s adding data, based on whether I need the row to be WholeDollar or Decimal Formatted, and pass it as an arg. All of the OO smarties right about now – who’ve gotten this far without wanting to go kick their cats b/c I’m so stupid for not having gone this route from day 1 – will probably say this is a good option. Yeah, probably. &lt;/li&gt;    &lt;li&gt;Add other approaches here. The internets love to make suggestions. So pretend I thought of all your suggestions, and pretend they’re here, in bullet point #4. :-) &lt;/li&gt;    &lt;li&gt;If your mind went to “FormatterStrategyFactory”, you need to go get yourself a beer &lt;/li&gt; &lt;/ol&gt;  &lt;h2&gt;Where My Head Is&lt;/h2&gt;  &lt;p&gt;Lately, I’ve been thinking that maybe the strict OO that I have come to love isn’t all that hot. No, it’s not because some douchebag wrote a blog post about how he loves procedural CF and he can’t “get” OO. It’s more about how perhaps OO has run its course, and perhaps since the world is going multi-core, and parallelism is just the way things are, and since “state” is the root of all evil with respect to parallel computing, that maybe OO isn’t the best model in the new world. Enter stage left, &lt;a href="http://en.wikipedia.org/wiki/Functional_programming" target="_blank"&gt;Functional Programming&lt;/a&gt;. I’ve been doing a lot of javascript programming lately, dabbling in Groovy, and reading Programming in Scala. So somewhere in my brain, I have this ADD-raddled set of neurons that can’t get a moment’s peace, and as I hit this dumbass dollar formatting problem – and all I want to do is get to lunch, get through the day, and go the hell home – this thought pops into my head:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/__j-6QTK4wT8/S0XTEmEkgKI/AAAAAAAAANY/vH8mLWVBNsU/s1600-h/closures_tweet%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="closures_tweet" border="0" alt="closures_tweet" src="http://lh6.ggpht.com/__j-6QTK4wT8/S0XTE-DBmuI/AAAAAAAAANc/EMmEfDssRrw/closures_tweet_thumb.png?imgmax=800" width="244" height="121" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;It kind of came unbidden. Up until that point, I had not done any serious investigation into closures, except what I knew about them from javascript. But it’s funny: in javascript, closures aren’t “a thing”. They are “the way things are”. It’s part of the language, like parentheses and colons and var and array.push(). If you’ve ever used jQuery or EXT, you’ve used closures and you maybe didn’t even know it.&lt;/p&gt;  &lt;p&gt;All of this is to say that in my head, thanks to the fact that I can’t focus on one thing lately for more than a few hours, I had these other languages creeping in saying “If you were programming in ME, this is how we’d solve it and you’d be on your way out the door”.&lt;/p&gt;  &lt;p&gt;I do not know if that is good or bad. Maybe it’s lazy? Maybe it’s impure? &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;But think about this:&lt;/strong&gt;&amp;#160; Wouldn’t it be sweet, if in my current position, I could tell my function: “Hey, Function, when you format this data, I want you to do it this way”&lt;/p&gt;  &lt;p&gt;And maybe it would look like this:&lt;/p&gt;  &lt;pre class="cf" name="code"&gt;tableBuilder.addTableRow(
  data=someArray,
  blah=whatever,
  formatter=&amp;quot;decimalFormatter&amp;quot;
);&lt;/pre&gt;

&lt;p&gt;And you’re thinking: “But dude, that looks exactly like what you described above, with the different Formatter classes, each with a single “format” method or whatever. But it’s not. Instead, formatter is a function, not an instance of a DecimalFormatter object I’ve declared elsewhere. That’s right, a function. And when tableBuilder does its &lt;strong&gt;drawText(), &lt;/strong&gt;it does it like this:&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;drawTextFromMacro(textMacroName, formatter(data[col]), startX, startY, startAmountRightX);&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;What your CFML might look like if it had closures &lt;/h2&gt;

&lt;p&gt;You should be wondering: “How did he define this function? What does it look like?”. And here, in imaginary CF, is the answer:&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;decimalFormatter = function(value){Formatter.formatWholeDollar(value,true,false)};

tableBuilder.addTableRow(
  data=someArray,
  blah=whatever,
  formatter=&amp;quot;decimalFormatter&amp;quot;
);&lt;/pre&gt;

&lt;p&gt;What’s happening in this imaginary example is that I’m passing a function I’ve defined in “ThingThatUsesTableBuilder”, named it “decimalFormatter”, and passed that function into the tableBuilder.addTableRow() method. TableBuilder then calls that function as if it were some function inside of itself. It looks completely natural.&amp;#160; But notice this: the call to the formatter(…) function has no idea about what that Formatter object is. It doesn’t know about its state. Hell, for all it knows, formatter() uses some other object to do its work. It doesn’t know, it doesn’t care. It just does it.&lt;/p&gt;

&lt;p&gt;Another example: Maybe the call to addTableRow looks like this:&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;tableBuilder.addTableRow(
  data=someArray,
  blah=whatever,
  formatter=&amp;quot;function(value){Formatter.formatWholeDollar(value,true,false)}&amp;quot;
);&lt;/pre&gt;

&lt;p&gt;See that: it’s defining the function on the fly. It uses the “guts” from that Formatter object that I discussed way back at the beginning, passing some additional params to control its behavior. Then, when drawTextFromMacro() gets that function as the formatter, it knows what the “Formatter” object is (this is the magic of closures), and it applies that formatWholeDollar() function to the data.&lt;/p&gt;

&lt;p&gt;Which brings us to….&lt;/p&gt;

&lt;h2&gt;What is a Closure?&lt;/h2&gt;

&lt;p&gt;I will get this wrong. I will miss the nuance and subtlety and beauty and power. That’s why you go find the answers yourself. So I’m going to give you my definition, based on a lot of reading and experimentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Closure_%28computer_science%29" target="_blank"&gt;Closures&lt;/a&gt; are function literals + party invites.&lt;/p&gt;

&lt;p&gt;Let’s talk about &lt;strong&gt;literals&lt;/strong&gt;. Literals are the things on the right. y = 5;&amp;#160; y is an int literal. you = “rad”;&amp;#160; “rad” is a String literal. MXUnitHombres = {frameworkJunkie=”Bill”, mockMaster=”Bob”, pluginDude=”Marc”, residentGrump=”Adam”, seleniumGuru=”MikeH”, cohibaSupplier=”MikeR”} is a Struct literal.&amp;#160; &lt;/p&gt;

&lt;p&gt;decimalFormatter = function(value){…..} shows a function literal on the right.&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;tableBuilder.addTableRow(
  data=someArray,
  blah=whatever,
  formatter=&amp;quot;function(value){Formatter.formatWholeDollar(value,true,false)}&amp;quot;
);&lt;/pre&gt;

&lt;p&gt;shows a function literal, passed as an argument to some other function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Party Invites&lt;/strong&gt;: When you define your function literal, that function might do simple things to the incoming arguments and not need the support of any additional functions/objects/variables. In that case, the thing you define really isn’t a closure. It’s just a function. But when you need your function to “remember” things about the world in which it was defined – in my case, I want my function to “remember” what the Formatter object was – that’s were we get into closures. In my example above, where I created the decimalFormatter function, its contents included a reference to the Formatter object I created earlier. When I pass my function into other objects and functions, it will still work – &lt;strong&gt;even though the recipient of my function has no notion of this “Formatter” object&lt;/strong&gt;. What I’ve done is I’ve invited the Formatter object to the party. I’ve said “Hey, you, you come along with me”. &lt;/p&gt;

&lt;p&gt;At risk of offending the purity gods, I’ll say this. Think of it like if your function literal &amp;quot;&lt;strong&gt;kept knowing about all the variables you invited into it even after that function was passed into a place that had no knowledge of those variables”&lt;/strong&gt;. Ben Nadel probably does as good a job as I’ve seen of &lt;a href="http://www.bennadel.com/index.cfm?dax=blog:1482.view" target="_blank"&gt;graphically describing this&lt;/a&gt;, in the context of javascript.&lt;/p&gt;

&lt;p&gt;So for example, look at that code up above, where I’m doing formatter=”function(value){Formatter.formatWholeDollar…}” as an argument to addTableRow(). In the refactored example, now that TableBuilder is no longer responsible for formatting, it doesn’t know anything about this Formatter object. It’s been relieved of that responsibility. How is it supposed to know what it means when it gets a function that calls this “Formatter.formatWholeDollar” thing?&amp;#160; Well….&lt;/p&gt;

&lt;p&gt;That’s closures. It knows about it because that’s how closures operate. They “enclose” or “close up” the stack around them and stuff em in a napsack and take it with them on their journey. They say to TableBuilder “tut tut, TableBuilder. Don’t fret. When you call me, I’m going to call this Formatter thing that I’ve got in me pocket, and ye shan’t worry, nor shall ye hurt him, because he’s mine and ye can’t keep him. So call me, I’ll do what I do, and go about yer business.”&lt;/p&gt;

&lt;h2&gt;Why is This Preferable?&lt;/h2&gt;

&lt;p&gt;In my case, this approach is preferable because it lets me very cleanly and easily encapsulate the behavior I want &lt;strong&gt;very close to the point at which I’ll use it&lt;/strong&gt;. Immediately before I call the function that adds the row of data, I define the formatting it will use. Now… all the nastiness behind formatWholeDollar() is safely tucked away. We want that stuff out of the picture. We do want to control those last two args though (whatever they are) for the purpose of just this one row of data. So for this one row, we say “I want to call formatWholeDollar, with these two extra args”. And we do that by defining a function that does just that.&lt;/p&gt;

&lt;h2&gt;What’s it look like in real life?&lt;/h2&gt;

&lt;p&gt;As part of my foray into closures, I wanted to see what it’d feel like to do a rough approximation of my problem in some different languages. I chose the ones closest to me at the moment: javascript, groovy, and scala.&lt;/p&gt;

&lt;p&gt;Here’s some javascript code that does kinda the same thing (stripped down for clarity). This is full HTML, so that muddies the picture somewhat, but I wanted to give you something you could copy/paste/run right in your browser.&amp;#160; It defines a Formatter object, an array, a function that does stuff with the array and takes a formatter function. Then it defines two functions (dollarAdder and zeroAdder). In the HTML, the onClick attributes call the doStuffWithArray function, passing in the function.&lt;/p&gt;

&lt;pre class="xml" name="code"&gt;&amp;lt;html&amp;gt;

 &amp;lt;head&amp;gt;
 
 &amp;lt;script&amp;gt;
     //ignore... just for printing stuff to screen
  function addRow(data){
   var newline = document.createTextNode(data);
   document.getElementById(&amp;quot;content&amp;quot;).appendChild(newline);
   document.getElementById(&amp;quot;content&amp;quot;).appendChild(document.createElement('br'));
  }
 
 
  values = [1,2,3,4,5];

  Formatter = new Object();
  Formatter.formatWithOptions = function(value,addDollarSign,addTwoZeroes){
   if(addDollarSign) value = '$' + value;
   if(addTwoZeroes) value += '.00';
   return value;
  };

    
  function doStuffWithArray(array,formatter){
   addRow(&amp;quot;Doing stuff with &amp;quot; + array);
   for(var el in array){
    addRow(&amp;quot;Using item &amp;quot; + array[el] + &amp;quot; as &amp;quot; + formatter(array[el]) );
   }
  }
  
  dollarAdder = function(value){return Formatter.formatWithOptions(value,true)};
  zeroAdder = function(value){return Formatter.formatWithOptions(value,false,true)};
 &amp;lt;/script&amp;gt;
 
 
 &amp;lt;/head&amp;gt;
 
 &amp;lt;body&amp;gt;
 
  &amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;dollar adder&amp;quot; onclick=&amp;quot;doStuffWithArray(values,dollarAdder);&amp;quot;&amp;gt;
  &amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;zero adder&amp;quot; onclick=&amp;quot;doStuffWithArray(values,zeroAdder);&amp;quot;&amp;gt;
  &amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;inline dollar and zero adder&amp;quot; onclick=&amp;quot;doStuffWithArray(values,function(value){return Formatter.formatWithOptions(value,true,true)});&amp;quot;&amp;gt;
  
  &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
 &amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;Run that, click the buttons, and you’ll see it in action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s some groovy:&lt;/strong&gt;&lt;/p&gt;

&lt;pre class="java" name="code"&gt;package formatters;
class Formatter { 
 def formatWithOptions(Number value, boolean addDollarSign, boolean addTwoZeroes){
  def newValue = value.toString()
  if(addDollarSign) newValue = &amp;quot;\$&amp;quot; + newValue
  if(addTwoZeroes) newValue += &amp;quot;.00&amp;quot;
  return newValue
 } 
}&lt;/pre&gt;

&lt;pre class="java" name="code"&gt;import formatters.Formatter

class Main {

 static main(args) {
  def formatter = new Formatter()
  def values = [1,2,3,4,5]
  def dollarFormatter = {formatter.formatWithOptions(it,true,false)}
  def zeroFormatter = {formatter.formatWithOptions(it,false,true)}
  
  def main = new Main()
  main.doStuffWithList(values,dollarFormatter)
  main.doStuffWithList(values,zeroFormatter)
  main.doStuffWithList(values,{formatter.formatWithOptions(it,true,true)})
 }
 
 def doStuffWithList(list,fn){
  println &amp;quot;Doing stuff with &amp;quot; + list  
  list.each {println &amp;quot;using item &amp;quot; + it + &amp;quot; as &amp;quot; + fn(it)}
  println &amp;quot;Doing other stuff...&amp;quot;
 }

}&lt;/pre&gt;

&lt;p&gt;Looks awfully similar to the javascript, doesn’t it? The main difference is groovy’s “it” keyword, as opposed to javascript where you can name your parameter whatever you like. The other difference is that I think this groovy example more clearly demonstrates the “Party Invite” concept. I’ve defined the “formatter” instance in the main method. I’ve defined the dollarFormatter and zeroFormatter function literals in main, using that formatter instance. I pass in those functions as arguments to another function (doStuffWithList), which lives in an instance of another object (because I’ve created a new “Main”), and that other function, in a new instance of Main, should by all reasoning have no notion of what “formatter.formatWithOptions….” means. But it does, because we’ve invited him to the party when we defined the function. This is why doStuffWithList doesn’t complain. In the javascript example, it very well might work because of the global nature of the “Formatter” I’ve declared. In this groovy example, it’s clearly shown that that is NOT happening.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;#160;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And finally, some scala:&lt;/strong&gt;&lt;/p&gt;

&lt;pre class="brush: scala"&gt;package formatters

object Formatter {

 def formatWithOptions(value:Number, addDollarSign:Boolean, addTwoZeroes:Boolean):String = {
   var newValue:String = value.toString()
   if(addDollarSign) newValue = &amp;quot;$&amp;quot; + newValue
   if(addTwoZeroes) newValue += &amp;quot;.00&amp;quot;
   return newValue
 }
}&lt;/pre&gt;

&lt;pre class="brush: scala"&gt;package main

import formatters._;

object Main {
  def main(args : Array[String]) : Unit = {
    val values:List[Number] = List(1,2,3,4,5)
    println (Formatter.formatWithOptions(values(1),true,false))
    
    //formatter.formatWithOptions(value,true,false)
    doStuffWithList(values,dollarFormatter)
    doStuffWithList(values,zeroFormatter)
    doStuffWithList(values, Formatter.formatWithOptions(_,true,true)  );
    
  }
  def dollarFormatter = Formatter.formatWithOptions(_:Number,true,false)
  def zeroFormatter = Formatter.formatWithOptions(_:Number,false,true)
  
  def doStuffWithList(list:List[Number], fn:(Number) =&amp;gt; String ) : Unit = {
    println(&amp;quot;Doing stuff with &amp;quot; + list)
    for(item &amp;lt;- list) println (&amp;quot;using item &amp;quot; + item + &amp;quot; as &amp;quot; + fn(item))
    println(&amp;quot;Doing other stuff&amp;quot;)
  }
}&lt;/pre&gt;

&lt;p&gt;I’m least comfortable with Scala, so it’s most likely I’m A) doing it a little wrong, B) doing it all kinds of wrong, or C) doing all this in 20 lines when I could contrive some angle-bracket-dash-colon-underscore-ridden beast to do it in a single line of code. The two main differences here are that I had to define the formatter functions outside the place where I was using them (i.e. I couldn’t define the functions inline with the rest of the code, like I could with Groovy and Javascript, though that’s probably b/c I don’t know what I’m doing), and the use of “_” as the argument name. Think of it as like “it” for Groovy, but with symbols instead, because Scala is queer for symbols.&lt;/p&gt;

&lt;h2&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;I included examples from other languages because I wanted to give you the &lt;strong&gt;feel&lt;/strong&gt; of closures. I do not intend to come across as one of those people who wants things in CF just because the cool kids have them.&amp;#160; Still… I like closures, a lot, and I believe that if they were added to CFML, in time many programmers would look back on the days before closures and think “Remember them days, Buck?” “Yeah, Grady. Them days sucked.” Closures add a level of convenience that will be shown to exceed even the convenience of struct and array literals added in CF8. &lt;/p&gt;

&lt;p&gt;The risk with closures is that it can invite a return to spaghetti, with large chunks of functionality stuck in-line. This is a Bad Thing(tm) and good programmers would be wise to avoid this trap. You’ll notice in my examples that I used closures more as a tidying-up. In fact, these examples show no original functionality. This is particularly important for testability. I trust that Formatter.formatWithOptions(value,true,false) and …(value,true,true) and …(value) all work correctly because they’ve all been unit tested. I do not care to test the closure I’ve defined because all it does is call functions on other objects. If CFML ever gets closures, you’ll start seeing all manner of bloggers railing against The Monster Closure. It will be good advice, so heed it.&lt;/p&gt;

&lt;p&gt;I am most certainly not the first person to want Closures in CFML. &lt;a href="http://www.barneyb.com/barneyblog/" target="_blank"&gt;One of my favorite CF dudes&lt;/a&gt; has been talking about it for a while, and &lt;a href="http://corfield.org" target="_blank"&gt;Sean Corfield&lt;/a&gt; told me that he planned to formally submit a recommendation to the CFML Advisory Committee. CF makes things easier, and I’d like to hear &lt;strong&gt;your thoughts&lt;/strong&gt; on how you might or might not use this feature were it added.&lt;/p&gt;

&lt;p&gt;Finally, I welcome any comments, criticisms, dialog, corrections, clarifications, etc. This was a “journey” of sorts for me. I used it to learn a lot more than I knew before, but surely I’ve gotten things wrong and so I’ll gladly correct any misinformation.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;--Marc&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-8998442753165755918?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/01/what-would-your-cfml-look-like-with.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>11</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-1973750947775262558.post-3620689923494572015</guid><pubDate>Fri, 01 Jan 2010 13:47:00 +0000</pubDate><atom:updated>2010-01-01T08:50:58.411-05:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>announcements</category><category domain='http://www.blogger.com/atom/ns#'>mxunit eclipse plugin</category><category domain='http://www.blogger.com/atom/ns#'>eclipse plugin</category><title>MXUnit Eclipse Plugin 1.2 Released</title><description>&lt;p&gt;Happy New Year!&lt;/p&gt;  &lt;p&gt;We’re happy to announce a new version of the MXUnit Eclipse plugin is available. The goal of this release is to simplify configuration for projects with respect to helping the plugin figure out the “cfc root” (i.e., turning c:\myproject\myapps\test\whatever\SomeTest.cfc into “myapps.test.whatever.SomeTest”). It’s always been a sore spot… this business of “What’s my webroot? Do I use the webroot or project properties? What if I have my project set up like this…?”&amp;#160; &lt;/p&gt;  &lt;p&gt;With this release, the “webroot” stuff is gone. The CFC root is now configured only at the project level. For current projects that live at the webroot (like c:\inetpub\wwwroot\MyApp”), this should not cause you to reconfigure anything. For projects that live in other places, you &lt;strong&gt;might&lt;/strong&gt; need to spend a minute configuring when you update the plugin. Of my dozen or so Eclipse projects, I had to update one. But my hope is that this change results in a much clearer configuration path for new users.&lt;/p&gt;  &lt;p&gt;In addition, the Plugin’s built-in help has been expanded and reorganized. Now, when you click on the green “Help” (?) Icon on the plugin view, you get a much simplified view of the help, designed to take you to the two most commonly asked questions: How do I configure this thing to get the correct CFC path, and what’s this RemoteFacade URL all about? It looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/__j-6QTK4wT8/Sz386RDmc4I/AAAAAAAAANA/SqIoTgJ2i5c/s1600-h/mxunitplugin_help_1%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mxunitplugin_help_1" border="0" alt="mxunitplugin_help_1" src="http://lh3.ggpht.com/__j-6QTK4wT8/Sz38639a74I/AAAAAAAAANE/K1H6sUCQjjE/mxunitplugin_help_1_thumb.png?imgmax=800" width="244" height="156" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you want more, there’s a link there to take you to the full help. When you click that link, you get taken to the introduction page for the Help. That looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/__j-6QTK4wT8/Sz387f51-NI/AAAAAAAAANI/H74IQiGFB_c/s1600-h/mxunitplugin_help_1_1%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mxunitplugin_help_1_1" border="0" alt="mxunitplugin_help_1_1" src="http://lh5.ggpht.com/__j-6QTK4wT8/Sz387q8NSPI/AAAAAAAAANM/Rfvs6R6cG-s/mxunitplugin_help_1_1_thumb.png?imgmax=800" width="244" height="156" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If you click the “Show in Contents” Button toward the top right of the view, you get the tree view of the help (This is the same view you’d get if you opened Help from “Help – Help Contents -- MXUnit”). If you expand the tree view, you’ll see the new organization of the Help content for the plugin. It looks thusly:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/__j-6QTK4wT8/Sz388MTSbFI/AAAAAAAAANQ/OsZNdVs-oIw/s1600-h/mxunitplugin_help_2%5B2%5D.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mxunitplugin_help_2" border="0" alt="mxunitplugin_help_2" src="http://lh3.ggpht.com/__j-6QTK4wT8/Sz388qkTylI/AAAAAAAAANU/jRBtGn_3bfM/mxunitplugin_help_2_thumb.png?imgmax=800" width="244" height="156" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;I added new documentation for configuring projects that need an Application.cfc, for projects that test CF9 ORM components, and all new documentation for the new way in which the CFC path for a test file is derived and configured. In addition, I added documentation on some things that MXUnit or the plugin doesn’t do but which weren’t clearly specified. Finally, I expanded the “Resources” section. Notice too that there are now links to “Troubleshooting”, “Frequently Asked Questions”, and “Tips and Tricks”, all from &lt;a href="http://wiki.mxunit.org/display/default/MXUnit+Documentation" target="_blank"&gt;our new Wiki&lt;/a&gt; (created and hosted by MXUnit hombre &lt;a href="http://cfrant.blogspot.com/" target="_blank"&gt;Adam Haskell&lt;/a&gt; (Side note: if you have any thoughts on what content should be added into the wiki, or how it could be better organized, we want to hear it!). I wanted to put this documentation on the wiki, and not directly in the plugin, so that I could easily update it without having to push new releases of the plugin. Plus, this way, more people can contribute.&lt;/p&gt;  &lt;p&gt;As always, if you have problems with or questions about the plugin, the fastest way to get answers is via the &lt;a href="http://groups.google.com/group/mxunit" target="_blank"&gt;Google group&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Test and be Happy.&lt;/p&gt;  &lt;p&gt;--Marc&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1973750947775262558-3620689923494572015?l=blog.mxunit.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.mxunit.org/2010/01/mxunit-eclipse-plugin-12-released.html</link><author>noreply@blogger.com (Marc Esher)</author><thr:total>0</thr:total></item></channel></rss>