<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.timmattison.com</title>
	<atom:link href="http://blog.timmattison.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.timmattison.com</link>
	<description>mostly tech</description>
	<lastBuildDate>Fri, 04 May 2012 13:06:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>How-To: Fix VMware kernel module compile issues with VMware Workstation 8.0.3 and Linux kernel 3.2.0</title>
		<link>http://blog.timmattison.com/archives/2012/05/04/how-to-fix-vmware-kernel-module-compile-issues-with-vmware-workstation-8-0-3-and-linux-kernel-3-2-0/</link>
		<comments>http://blog.timmattison.com/archives/2012/05/04/how-to-fix-vmware-kernel-module-compile-issues-with-vmware-workstation-8-0-3-and-linux-kernel-3-2-0/#comments</comments>
		<pubDate>Fri, 04 May 2012 13:06:30 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[VMware]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=741</guid>
		<description><![CDATA[Today I upgraded to VMware Workstation 8.0.3 and immediately I ran into the following error message: make[1]: Entering directory `/usr/src/linux-headers-3.2.0-2-amd64' CC [M] /tmp/vmware-root/modules/vmnet-only/userif.o CC [M] /tmp/vmware-root/modules/vmnet-only/netif.o CC [M] /tmp/vmware-root/modules/vmnet-only/filter.o /tmp/vmware-root/modules/vmnet-only/userif.c: In function ‘VNetCsumCopyDatagram’: /tmp/vmware-root/modules/vmnet-only/userif.c:520:3: error: incompatible type for argument 1 of ‘kmap’ /usr/src/linux-headers-3.2.0-2-common/include/linux/highmem.h:48:21: note: expected ‘struct page *’ but argument is of type ‘const struct [...]]]></description>
			<content:encoded><![CDATA[<p>Today I upgraded to VMware Workstation 8.0.3 and immediately I ran into the following error message:</p>
<pre>make[1]: Entering directory `/usr/src/linux-headers-3.2.0-2-amd64'
  CC [M]  /tmp/vmware-root/modules/vmnet-only/userif.o
  CC [M]  /tmp/vmware-root/modules/vmnet-only/netif.o
  CC [M]  /tmp/vmware-root/modules/vmnet-only/filter.o
/tmp/vmware-root/modules/vmnet-only/userif.c: In function ‘VNetCsumCopyDatagram’:
/tmp/vmware-root/modules/vmnet-only/userif.c:520:3: error: incompatible type for argument 1 of ‘kmap’
/usr/src/linux-headers-3.2.0-2-common/include/linux/highmem.h:48:21: note: expected ‘struct page *’ but argument is of type ‘const struct <anonymous>’
/tmp/vmware-root/modules/vmnet-only/userif.c:523:3: error: incompatible type for argument 1 of ‘kunmap’
/usr/src/linux-headers-3.2.0-2-common/include/linux/highmem.h:54:20: note: expected ‘struct page *’ but argument is of type ‘const struct <anonymous>’
/tmp/vmware-root/modules/vmnet-only/netif.c: In function ‘VNetNetIfSetup’:
/tmp/vmware-root/modules/vmnet-only/netif.c:134:7: error: unknown field ‘ndo_set_multicast_list’ specified in initializer
/tmp/vmware-root/modules/vmnet-only/netif.c:134:7: warning: initialization from incompatible pointer type [enabled by default]
/tmp/vmware-root/modules/vmnet-only/netif.c:134:7: warning: (near initialization for ‘vnetNetifOps.ndo_validate_addr’) [enabled by default]
make[4]: *** [/tmp/vmware-root/modules/vmnet-only/userif.o] Error 1
make[4]: *** Waiting for unfinished jobs....
make[4]: *** [/tmp/vmware-root/modules/vmnet-only/netif.o] Error 1
</pre>
<p>After lots of Googling I found <a href="http://weltall.heliohost.org/wordpress/2012/01/26/vmware-workstation-8-0-2-player-4-0-2-fix-for-linux-kernel-3-2-and-3-3/">a blog post with a patch for kernels 3.2.0 and 3.3.0</a>.  Unfortunately when I tried to run the patch it failed and said:</p>
<pre>Sorry, this script is only for VMWare WorkStation 8.0.2 or VMWare Player 4.0.2. Exiting</pre>
<p>In order to fix this open up the script after you download it and change the line this line:</p>
<pre class="syntax bash">
vmreqver=8.0.2
</pre>
<p>To this:</p>
<pre class="syntax bash">
vmreqver=8.0.3
</pre>
<p>Re-run the script and you should be good to go.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/05/04/how-to-fix-vmware-kernel-module-compile-issues-with-vmware-workstation-8-0-3-and-linux-kernel-3-2-0/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Tips for debugging Spring&#8217;s @Transactional annotation</title>
		<link>http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/</link>
		<comments>http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/#comments</comments>
		<pubDate>Thu, 19 Apr 2012 14:31:14 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=737</guid>
		<description><![CDATA[For over a week now I&#8217;ve been cleaning up some legacy code that uses Spring and Hibernate to persist and process data in a SQL database. The code works but it doesn&#8217;t follow the strict philosophy of service oriented architecture in the sense that there are several places that Spring and Hibernate weren&#8217;t doing what [...]]]></description>
			<content:encoded><![CDATA[<p>For over a week now I&#8217;ve been cleaning up some legacy code that uses Spring and Hibernate to persist and process data in a SQL database.  The code works but it doesn&#8217;t follow the strict philosophy of service oriented architecture in the sense that there are several places that Spring and Hibernate weren&#8217;t doing what they were expected to do and a few workarounds had to be implemented.  Since we were bringing more programmers on board I wanted to make sure that everything played by the rules and was easy to update so I had to learn a lot that I had glossed over in the past.</p>
<p>With some creative Googling I found two invaluable resources that I need to give credit to:</p>
<ul>
<li><a href="http://java.dzone.com/articles/monitoring-declarative-transac?page=0,1" title="Monitoring Declarative Transactions in Spring" target="_blank">Monitoring Declarative Transactions in Spring</a></li>
<li><a href="http://stackoverflow.com/questions/3037006/starting-new-transaction-in-spring-bean" title="Starting new transactions in Spring bean" target="_blank">Starting new transactions in Spring bean</a></li>
</ul>
<p>Here&#8217;s what I distilled out of everything I went through:</p>
<ol>
<li>@Transactional annotations only work on public methods.  If you have a private or protected method with this annotation there&#8217;s no (easy) way for Spring AOP to see the annotation.  It doesn&#8217;t go crazy trying to find them so make sure all of your annotated methods are public.</li>
<li>Transaction boundaries are only created when properly annotated (see above) methods are called through a Spring proxy.  This means that you need to call your annotated method directly through an @Autowired bean or the transaction will never start.  If you call a method on an @Autowired bean that isn&#8217;t annotated which itself calls a public method that is annotated <strong><em>YOUR ANNOTATION IS IGNORED</em></strong>.  This is because Spring AOP is only checking annotations when it first enters the @Autowired code.</li>
<li>Never blindly trust that your @Transactional annotations are actually creating transaction boundaries.  When in doubt test whether a transaction really is active (see below)</li>
</ol>
<p>My first problem was that the code was annotated improperly like this:</p>
<pre class="syntax java">
/**
 * This code example is BAD code, do not use it!
 */
class NonWorkingMyClass {

  @Autowired
  protected MyService myService;

  public void calledFirst() {
    // Do some setup work...

    // Call our internal method
    calledSecond();
  }

  @Transactional
  private void calledSecond() {
    MyObject myObject = myService.retrieveLatest();

    // Update some object fields
    myObject.setName(&quot;New Name&quot;);
  }
}</pre>
<p>In this case someone would call NonWorkingMyClass.calledFirst(), it would then call calledSecond() and try to update the name field.  This works if your XML configuration is set up properly but it will not be in a transaction.  This can cause concurrency issues that won&#8217;t show up until it&#8217;s really inconvenient.</p>
<p>Here&#8217;s the working version of that code:</p>
<pre class="syntax java">
/**
 * This code example works
 */
class WorkingMyClass {

  @Autowired
  protected MyService myService;

  @Transactional
  public void calledFirst() {
    // Do some setup work...

    // Call our internal method
    calledSecond();
  }

  private void calledSecond() {
    MyObject myObject = myService.retrieveLatest();

    // Update some object fields
    myObject.setName(&quot;New Name&quot;);
  }
}</pre>
<p>Now when someone called WorkingMyClass.calledFirst() it would do what you expect in a transaction and the transaction boundaries are properly respected.</p>
<p>This looks like a simple fix that should only take a few minutes but finding out that was the problem involved turning on lots of Spring DEBUG level logging, Googling, and actually testing to make sure the transactions were active.  Before I knew what I know now I used some code from the first site I listed to show if I was inside a transaction or not.  I was shocked and relieved when it showed that I wasn&#8217;t because it meant the concurrency issues weren&#8217;t due to bad programming, just bad configuration.  Here are the methods that I came up with that you can use to see if you are in a transaction and even force your code to throw an exception if it isn&#8217;t.  This can be invaluable if someone messes up an annotation in the future or breaks your XML configuration.</p>
<p>This code belongs in a utility class that is accessible from anywhere.  There are two flags you will need to put somewhere:</p>
<p>transactionDebugging &#8211; Indicates we should do the transaction tests<br />
verboseTransactionDebugging &#8211; Indicates we should print debug messages with the transaction tests</p>
<p>verboseTransactionDebugging has no effect if transactionDebugging is false.</p>
<pre class="syntax java">
class DebugUtils {
	private static final transactionDebugging = true;
	private static final verboseTransactionDebugging = true;

	public static void showTransactionStatus(String message) {
		System.out.println(((transactionActive()) ? &quot;[+] &quot; : &quot;[-] &quot;) + message);
	}

	// Some guidance from: http://java.dzone.com/articles/monitoring-declarative-transac?page=0,1
	public static boolean transactionActive() {
		try {
			ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
			Class tsmClass = contextClassLoader.loadClass(&quot;org.springframework.transaction.support.TransactionSynchronizationManager&quot;);
			Boolean isActive = (Boolean) tsmClass.getMethod(&quot;isActualTransactionActive&quot;, null).invoke(null, null);

			return isActive;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}

		// If we got here it means there was an exception
		throw new IllegalStateException(&quot;ServerUtils.transactionActive was unable to complete properly&quot;);
	}

	public static void transactionRequired(String message) {
		// Are we debugging transactions?
		if (!transactionDebugging) {
			// No, just return
			return;
		}

		// Are we doing verbose transaction debugging?
		if (verboseTransactionDebugging) {
			// Yes, show the status before we get to the possibility of throwing an exception
			showTransactionStatus(message);
		}

		// Is there a transaction active?
		if (!transactionActive()) {
			// No, throw an exception
			throw new IllegalStateException(&quot;Transaction required but not active [&quot; + message + &quot;]&quot;);
		}
	}
}
</pre>
<p>In our previous code example we could use these new methods like this:</p>
<pre class="syntax java">
/**
 * This code example works
 */
class WorkingMyClass {

  @Autowired
  protected MyService myService;

  @Transactional
  public void calledFirst() {
    // Make sure we're using transactions.  Include the name of the class and method
    //   so it is easier to track down later if there are problems.
    DebugUtils.transactionRequired(&quot;WorkingMyClass.calledFirst&quot;);

    // Do some setup work...

    // Call our internal method
    calledSecond();
  }

  private void calledSecond() {
    MyObject myObject = myService.retrieveLatest();

    // Update some object fields
    myObject.setName(&quot;New Name&quot;);
  }
}</pre>
<p>That&#8217;s it.  Post in the comments if this helps you out or if you want to add to the code.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How-To: Get Verizon&#8217;s Media Manager to read content from a network location</title>
		<link>http://blog.timmattison.com/archives/2012/04/17/how-to-get-verizons-media-manager-to-read-content-from-a-network-location/</link>
		<comments>http://blog.timmattison.com/archives/2012/04/17/how-to-get-verizons-media-manager-to-read-content-from-a-network-location/#comments</comments>
		<pubDate>Tue, 17 Apr 2012 19:45:12 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Verizon FiOS]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=732</guid>
		<description><![CDATA[I ran into this problem today too when I first got FiOS installed. Mapping a network drive won&#8217;t work but using &#8220;subst&#8221; will. I now have Media Manager reading my pictures over a network connection. Here&#8217;s how to do it: Open the start menu Type &#8220;cmd&#8221; Right click on &#8220;cmd&#8221; and select &#8220;Run as administrator&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into this problem today too when I first got FiOS installed.  Mapping a network drive won&#8217;t work but using &#8220;subst&#8221; will.  I now have Media Manager reading my pictures over a network connection.  Here&#8217;s how to do it:</p>
<ol>
<li>Open the start menu</li>
<li>Type &#8220;cmd&#8221;</li>
<li>Right click on &#8220;cmd&#8221; and select &#8220;Run as administrator&#8221;</li>
<li>Run subst like this:
<pre class="syntax bash">subst DRIVE: LOCATION</pre>
<p>  DRIVE: will need to be a free drive letter like &#8220;F:&#8221;, &#8220;G:&#8221;, etc<br />
  LOCATION will need to be the <a href="http://en.wikipedia.org/wiki/Path_(computing)#Uniform_Naming_Convention" title="Uniform Naming Convention" target="_blank">UNC path</a> to your network share like this &#8220;\\myothercomputer\pictures\&#8221;<br />
  Don&#8217;t forget to include the quotes if your LOCATION has spaces in it!</li>
<li>Restart Media Manager and try to add the new virtual drive to it, it should start working right away</li>
</ol>
<p>You may need to do this on each reboot.  I never reboot this computer so I haven&#8217;t tested it yet.  You can put these commands in a batch file to make your life easier but you&#8217;ll need to make sure the batch file runs as an administrator.</p>
<p>Let me know in the comments if it works for you or not.  If not I can probably help work out any kinks with you.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/04/17/how-to-get-verizons-media-manager-to-read-content-from-a-network-location/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tip: Fix &#8220;&#8216;xterm&#8217;: unknown terminal type&#8221; messages in Debian</title>
		<link>http://blog.timmattison.com/archives/2012/04/12/tip-fix-xterm-unknown-terminal-type-messages-in-debian/</link>
		<comments>http://blog.timmattison.com/archives/2012/04/12/tip-fix-xterm-unknown-terminal-type-messages-in-debian/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 14:32:57 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Debian]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=728</guid>
		<description><![CDATA[This one has been a bit of a nuisance on newly spooled up Debian instances for me lately. When I try to run &#8220;top&#8221; or &#8220;clear&#8221; or really anything that does something with the terminal I get the following message: 'xterm': unknown terminal type. This is because either you haven&#8217;t installed ncurses-term (unlikely) or a [...]]]></description>
			<content:encoded><![CDATA[<p>This one has been a bit of a nuisance on newly spooled up Debian instances for me lately.  When I try to run &#8220;top&#8221; or &#8220;clear&#8221; or really anything that does something with the terminal I get the following message:</p>
<pre class="syntax bash">'xterm': unknown terminal type.</pre>
<p>This is because either you haven&#8217;t installed ncurses-term (unlikely) or a symlink from /lib/terminfo/x/xterm to /usr/share/terminfo/x/xterm is missing.  To cover all possibilities do this:</p>
<pre class="syntax bash">sudo apt-get install ncurses-term
sudo ln -s /lib/terminfo/x/xterm /usr/share/terminfo/x/xterm</pre>
<p>Poof, your terminal works again!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/04/12/tip-fix-xterm-unknown-terminal-type-messages-in-debian/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How-To: Write a Netduino driver for the Grove chainable RGB LED</title>
		<link>http://blog.timmattison.com/archives/2012/03/29/how-to-write-a-netduino-driver-for-the-grove-chainable-rgb-led/</link>
		<comments>http://blog.timmattison.com/archives/2012/03/29/how-to-write-a-netduino-driver-for-the-grove-chainable-rgb-led/#comments</comments>
		<pubDate>Thu, 29 Mar 2012 14:58:01 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Netduino]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=724</guid>
		<description><![CDATA[A lot of people probably look at hardware that doesn&#8217;t come with drivers for the Netduino or Arduino and don&#8217;t even consider picking it up if they&#8217;re new to this scene. In this article I&#8217;ll show you how I wrote a driver for Grove&#8217;s chainable RGB LED by just carefully reading the specs and experimenting. [...]]]></description>
			<content:encoded><![CDATA[<p>A lot of people probably look at hardware that doesn&#8217;t come with drivers for the Netduino or Arduino and don&#8217;t even consider picking it up if they&#8217;re new to this scene.  In this article I&#8217;ll show you how I wrote a driver for <a href="http://www.epictinker.com/Grove-Chainable-RGB-LED-p/com53140p.htm" title="Grove's chainable RGB LED" target="_blank">Grove&#8217;s chainable RGB LED</a> by just carefully reading the specs and experimenting.  I am no Netduino expert, I have only written a tiny bit of code for it since I got it, but this just reinforces how easy some drivers can be to write.</p>
<p>Keep in mind that my illustration of how easy it was to write this driver is not a reflection on how easy it is to write <strong><em>all</em></strong> drivers.  Some drivers take a ton of work.  Make sure you read the documentation before you buy something so you don&#8217;t get stuck with some hardware you can&#8217;t use.</p>
<p>My first step was to find <a href="http://www.seeedstudio.com/wiki/index.php?title=Twig_-_Chainable_RGB_LED" title="Grove Chainable RGB LED documentation" target="_blank">the documentation for the protocol for this device</a>.  I then scanned around to find the &#8220;Communication Protocol&#8221; and started digging.  What this showed me is that there are two connections to support the protocol for this device.  The first connection is called &#8220;CIN&#8221; for clock input and the second connection is called &#8220;DIN&#8221; for data input.  Simple enough, especially if we&#8217;re using the standard Grove base shield and connectors.  Just hook it up and make sure you keep track of which port you&#8217;re using and you&#8217;re ready to start programming.  I used header 6 on my base shield so the relevant pins for me were D6 and D7.  D6 was CIN and D7 was DIN.</p>
<p>Now you&#8217;ll see that there are six well defined bullet points explaining the basics of the protocol:</p>
<ul>
<li>Data needs to be ready before CIN, and DIN gets into the buffer on the rising edge of CIN.</li>
<li>First 32 bits &#8217;0&#8242; are Start Frame</li>
<li>Flag bit is two &#8217;1&#8242;</li>
<li>Calibration bits B7&#8242;,B6&#8242;;G7&#8242;,G6&#8242; and R7&#8242;,R6&#8242; are inverse codes of B7,B6;G7,G6 and R7,R6</li>
<li>Gray data MSB first, and the order is BLUE, GREEN, and RED</li>
<li>After all nodes data sent, need to seed another 32 bits &#8217;0&#8242; to update the data</li>
</ul>
<p>Let&#8217;s step through these one by one to figure out how to send data to this device.</p>
<p>They first tell us that &#8220;data needs to be ready before CIN, and DIN gets into the buffer on the rising edge of CIN&#8221;.  What this really translates to for you when programming is that when you want to send a bit to the device you should set that bit on the DIN pin (either 1 or 0), then set the CIN pin to high, and then set the CIN pin back to low.  Now you&#8217;ve sent one bit of data to the device.  Abstraction will make it so we can do this thinking once and then fall back on it later so let&#8217;s write a function that sends one bit:</p>
<pre class="syntax csharp">
private void sendBit(bool bit)
{
    // Get DIN into the proper state
    din.Write(bit);

    // Set the clock high
    cin.Write(true);

    // Set the clock low
    cin.Write(false);
}
</pre>
<p>This function makes the assumption that you&#8217;ve defined cin and din elsewhere.  The setup for them in my case (using pins D6 and D7 as I described above) would look like this:</p>
<pre class="syntax csharp">
// Use D6 for CIN and D7 for DIN (Grove Base Shield v1.2 header #6)
OutputPort cin = new OutputPort(Pins.GPIO_PIN_D6, false);
OutputPort din = new OutputPort(Pins.GPIO_PIN_D7, false);
</pre>
<p>Now they tell us that the first 32 bits are all zeroes and that this is called a start frame.  This makes me think it would be a good idea to expand our abstraction to let us send bytes and then write another function that would send this start frame.  That would look like this:</p>
<pre class="syntax csharp">
private void sendByte(byte data)
{
    // Send the bits MSB first
    sendBit((data &amp; 0x80) == 0x80);
    sendBit((data &amp; 0x40) == 0x40);
    sendBit((data &amp; 0x20) == 0x20);
    sendBit((data &amp; 0x10) == 0x10);
    sendBit((data &amp; 0x08) == 0x08);
    sendBit((data &amp; 0x04) == 0x04);
    sendBit((data &amp; 0x02) == 0x02);
    sendBit((data &amp; 0x01) == 0x01);
}

private void sendStartFrame()
{
    // The start frame is 32 bits of zeroes
    sendByte(0);
    sendByte(0);
    sendByte(0);
    sendByte(0);
}
</pre>
<p>In the sendByte function I&#8217;m taking a byte and using logical AND and equals to extract the bits one by one.  One of the next bullet points says the data is MSB first so we want to get the most significant (ie. largest value holding) bits first so that&#8217;s how I went about sending the bits.  Now that we can send bytes sending the start frame is as easy as calling that function four times with the value 0.</p>
<p>Next they talk about flag bits.  In the protocol it shows that after the start frame there are some flag bits.  This tells us the two flag bits are both ones.  Here&#8217;s a simple function that can do that:</p>
<pre class="syntax csharp">
private void sendFlagBits()
{
    // The flag bits are two 1s
    sendBit(true);
    sendBit(true);
}
</pre>
<p>Now this part gets a bit trickier but not too bad.  They tell us that we need to send the inverse of B7, B6, G7, G6, R7, R6, followed by the actual color data itself as bytes.  B7 and B6 are the two highest bits in the blue color component, G7 and G6 are the two highest bits in the green color component, and R7 and R6 are the two highest bits in the red color component.  Sending that data with the functions we built up now is really easy.</p>
<pre class="syntax csharp">
private void sendColorData(byte red, byte green, byte blue)
{
    // Send the inverse bits of the B7, B6, G7, G6, R7, R6
    sendBit((blue &amp; 0x80) != 0x80);
    sendBit((blue &amp; 0x40) != 0x40);
    sendBit((green &amp; 0x80) != 0x80);
    sendBit((green &amp; 0x40) != 0x40);
    sendBit((red &amp; 0x80) != 0x80);
    sendBit((red &amp; 0x40) != 0x40);

    // Send the actual colors
    sendByte((byte)blue);
    sendByte((byte)green);
    sendByte((byte)red);
}
</pre>
<p>We&#8217;re almost there, there&#8217;s only one step left!  Now we need to send the end frame.  It turns out that the end frame is the same as the start frame but to keep the code readable I did this:</p>
<pre class="syntax csharp">
private void sendEndFrame()
{
    // The end frame is the same as the start frame
    sendStartFrame();
}
</pre>
<p>Now you have enough information to send a color to your device.  We should probably wrap it up so that we can make it even easier to use though.  Let&#8217;s just think about how this is going to be used in practice.  A typical user will have a few of these LEDs chained together but for testing you might want to use just one.  We know that the protocol requires a start frame, then flag bits, then color data, and the end frame if we use a single LED but for two LEDs it looks like this:</p>
<ul>
<li>Send start frame</li>
<li>Send flag bits</li>
<li>Send color data</li>
<li>Send flag bits</li>
<li>Send color data</li>
<li>Send end frame</li>
</ul>
<p>So for our first LED we want to send the start frame, the flag bits and the color data.  For our last LED we want to send flag bits, the color data, and the end frame.  Here&#8217;s a function that does that:</p>
<pre class="syntax csharp">
private void setColor(byte red, byte green, byte blue, bool first, bool last)
{
    // Is this the first color?
    if (first)
    {
        // Yes, send the start frame
        sendStartFrame();
    }
    else
    {
        // No, do nothing
    }

    // Send the flag bits
    sendFlagBits();

    // Send the colors
    sendColorData(red, green, blue);

    // Is this the last color?
    if (last)
    {
        // Yes, send the end frame
        sendEndFrame();
    }
    else
    {
        // No, do nothing
    }
}
</pre>
<p>The extra else blocks have no impact on the executable generated so they&#8217;re just there for clarity.  You can remove them if you want.  Now if you want to send a bunch of colors to a string of three LEDs you can do this:</p>
<pre class="syntax csharp">
setColor(255, 0, 0, true, false);
setColor(0, 255, 0, false, false);
setColor(0, 0, 255, false, true);
</pre>
<p>That would set a string of three LEDs to solid red, solid green, and solid blue.  That&#8217;s it, your driver is written!</p>
<p>Check out <a href="https://github.com/timmattison/timmattison-netduino-drivers/tree/master/drivers/chainable-rgbled-grove/chainable-rgbled-grove" title="My Grove chainable RGB LED driver" target="_blank">my driver on Github</a> to see a few more enhancements I added.  My code has an abstraction of a color from three integers into an RGB object so it&#8217;s easier to pass around and also has a function that can set a string of LEDs from an array of RGB objects.  There&#8217;s some sample code as well and if you want to see the system in action check out these simple videos:</p>
<ul>
<li><a href="http://www.youtube.com/watch?v=cOlJoXWr_qQ" title="Cycling random colors" target="_blank">Cycling random colors</a></li>
<li><a href="http://www.youtube.com/watch?v=b5X3mvLbBf8" title="Cycling red, green, and blue" target="_blank">Cycling red, green, and blue</a></li>
</ul>
<p>Post in the comments and share your thoughts and project ideas.  If you use this library please let me know!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/03/29/how-to-write-a-netduino-driver-for-the-grove-chainable-rgb-led/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How-To: Fix Maven errors in Eclipse when getting started with Heroku</title>
		<link>http://blog.timmattison.com/archives/2012/03/28/how-to-fix-maven-errors-in-eclipse-when-getting-started-with-heroku/</link>
		<comments>http://blog.timmattison.com/archives/2012/03/28/how-to-fix-maven-errors-in-eclipse-when-getting-started-with-heroku/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 13:15:24 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[How-To]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=719</guid>
		<description><![CDATA[I haven&#8217;t used Heroku much yet but with the addition of Java to their platform I&#8217;m starting to see it as a really interesting option. Yesterday I watched a great video on how to get started with Java on Heroku. It went well until I tried converting my project to a Maven project. Then I [...]]]></description>
			<content:encoded><![CDATA[<p>I haven&#8217;t used Heroku much yet but with the addition of Java to their platform I&#8217;m starting to see it as a really interesting option.  Yesterday I watched <a href="http://www.youtube.com/watch?feature=player_embedded&#038;v=mkmWwA0EoGg#!" title="Getting started with Java on Heroku" target="_blank">a great video on how to get started with Java on Heroku</a>.  It went well until I tried converting my project to a Maven project.  Then I got this error message in all of my pom.xml files:</p>
<p><code>Plugin execution not covered by lifecycle configuration</code></p>
<p>I checked the usual places but didn&#8217;t find a solution to the issue.  Then I decided to try adding the m2e plugin from this update site:</p>
<p><code>http://download.eclipse.org/technology/m2e/releases</code></p>
<p>After adding the plugin and restarting my IDE I got two different error messages:</p>
<p><code>maven-dependency-plugin (goals "copy-dependencies", "unpack") is not supported by m2e.</code><br />
<code>Project configuration is not up-to-date with pom.xml.  Run project configuration update.</code></p>
<p>The second error had a quick fix so I tried that and it worked.  Now the Java example application that uses the Play framework and the one that uses Spring MVC and Hibernate both work.  However, the ones that used JAX-RS and embedded Jetty did not.  They still showed the maven-dependency-plugin error.  The fix is to add the following XML in the build section of your pom.xml:</p>
<pre class="syntax xml">
&lt;pluginManagement&gt;
	&lt;plugins&gt;
		&lt;plugin&gt;
			&lt;groupId&gt;org.eclipse.m2e&lt;/groupId&gt;
				&lt;artifactId&gt;lifecycle-mapping&lt;/artifactId&gt;
				&lt;version&gt;1.0.0&lt;/version&gt;
				&lt;configuration&gt;
					&lt;lifecycleMappingMetadata&gt;
						&lt;pluginExecutions&gt;
							&lt;pluginExecution&gt;
								&lt;pluginExecutionFilter&gt;
									&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
									&lt;artifactId&gt;maven-dependency-plugin&lt;/artifactId&gt;
									&lt;versionRange&gt;[1.0.0,)&lt;/versionRange&gt;
									&lt;goals&gt;
										&lt;goal&gt;copy-dependencies&lt;/goal&gt;
									&lt;/goals&gt;
								&lt;/pluginExecutionFilter&gt;
								&lt;action&gt;
									&lt;ignore /&gt;
								&lt;/action&gt;
							&lt;/pluginExecution&gt;
						&lt;/pluginExecutions&gt;
					&lt;/lifecycleMappingMetadata&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;
		&lt;/plugins&gt;
	&lt;/pluginManagement&gt;
</pre>
<p>After that you&#8217;ll have to do the quick fix for the error &#8220;Project configuration is not up-to-date&#8221; again and then you&#8217;ll be error free, at least in your pom.xml&#8230;</p>
<p>Post in the comments and let me know if it worked or if you need any help.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/03/28/how-to-fix-maven-errors-in-eclipse-when-getting-started-with-heroku/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tip: Handle failed tasks throwing &#8220;ENOENT&#8221; errors in Hadoop</title>
		<link>http://blog.timmattison.com/archives/2012/03/21/tip-handle-failed-tasks-throwing-enoent-errors-in-hadoop/</link>
		<comments>http://blog.timmattison.com/archives/2012/03/21/tip-handle-failed-tasks-throwing-enoent-errors-in-hadoop/#comments</comments>
		<pubDate>Wed, 21 Mar 2012 23:09:48 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=713</guid>
		<description><![CDATA[Today when I tried to run a new Hadoop job I got the following error: [exec] 12/03/21 22:51:47 INFO mapred.JobClient: Task Id : attempt_201203212250_0001_m_000002_1, Status : FAILED [exec] Error initializing attempt_201203212250_0001_m_000002_1: [exec] ENOENT: No such file or directory [exec] at org.apache.hadoop.io.nativeio.NativeIO.chmod(Native Method) [exec] at org.apache.hadoop.fs.RawLocalFileSystem.setPermission(RawLocalFileSystem.java:521) [exec] at org.apache.hadoop.fs.RawLocalFileSystem.mkdirs(RawLocalFileSystem.java:344) [exec] at org.apache.hadoop.mapred.JobLocalizer.initializeJobLogDir(JobLocalizer.java:240) [exec] at org.apache.hadoop.mapred.DefaultTaskController.initializeJob(DefaultTaskController.java:216) [exec] [...]]]></description>
			<content:encoded><![CDATA[<p>Today when I tried to run a new Hadoop job I got the following error:</p>
<pre class="syntax bash">     [exec] 12/03/21 22:51:47 INFO mapred.JobClient: Task Id : attempt_201203212250_0001_m_000002_1, Status : FAILED
     [exec] Error initializing attempt_201203212250_0001_m_000002_1:
     [exec] ENOENT: No such file or directory
     [exec] 	at org.apache.hadoop.io.nativeio.NativeIO.chmod(Native Method)
     [exec] 	at org.apache.hadoop.fs.RawLocalFileSystem.setPermission(RawLocalFileSystem.java:521)
     [exec] 	at org.apache.hadoop.fs.RawLocalFileSystem.mkdirs(RawLocalFileSystem.java:344)
     [exec] 	at org.apache.hadoop.mapred.JobLocalizer.initializeJobLogDir(JobLocalizer.java:240)
     [exec] 	at org.apache.hadoop.mapred.DefaultTaskController.initializeJob(DefaultTaskController.java:216)
     [exec] 	at org.apache.hadoop.mapred.TaskTracker$4.run(TaskTracker.java:1352)
     [exec] 	at java.security.AccessController.doPrivileged(Native Method)
     [exec] 	at javax.security.auth.Subject.doAs(Subject.java:416)
     [exec] 	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1157)
     [exec] 	at org.apache.hadoop.mapred.TaskTracker.initializeJob(TaskTracker.java:1327)
     [exec] 	at org.apache.hadoop.mapred.TaskTracker.localizeJob(TaskTracker.java:1242)
     [exec] 	at org.apache.hadoop.mapred.TaskTracker.startNewTask(TaskTracker.java:2541)
     [exec] 	at org.apac
</pre>
<p>It wasn&#8217;t immediately apparent to me what file wasn&#8217;t found from the error messages so I checked the logs, the JobTracker, my code, ran some known good jobs that also failed, basically everything I could think of.  It turns out that due to me accidentally running a script as &#8220;root&#8221; (don&#8217;t worry, it was only on my desktop) that the permissions of several files in the hdfs user&#8217;s home directory had changed ownership to &#8220;root&#8221;.  Because of that Hadoop was unable to create files in the /usr/lib/hadoop-0.20 directory.</p>
<p>NOTE: These steps assume you are using Hadoop 0.20.  Adjust the paths in the commands accordingly if you aren&#8217;t.</p>
<p>If you want a quick fix try these steps (only if you take full responsibility for anything that may go wrong):</p>
<ol>
<li>Stop Hadoop using the stop-all.sh script as the hdfs user</li>
<li>su to the hdfs user</li>
<li>Run this:
<pre class="syntax bash">chown -R hdfs:hdfs /usr/lib/hadoop-0.20 /var/*/hadoop-0.20</pre>
</li>
<li>Restart Hadoop using the start-all.sh script as the hdfs user</li>
</ol>
<p>Now your jobs should start running again.  Post in the comments if this procedure works for you or if you need any help.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/03/21/tip-handle-failed-tasks-throwing-enoent-errors-in-hadoop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How-To: Install Perl debugging in Eclipse on Debian/Ubuntu</title>
		<link>http://blog.timmattison.com/archives/2012/03/14/how-to-install-perl-debugging-in-eclipse-on-debian-ubuntu/</link>
		<comments>http://blog.timmattison.com/archives/2012/03/14/how-to-install-perl-debugging-in-eclipse-on-debian-ubuntu/#comments</comments>
		<pubDate>Wed, 14 Mar 2012 16:31:48 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=705</guid>
		<description><![CDATA[If you&#8217;re looking to use Eclipse as a debugger for your Perl scripts things can get a bit hairy quickly. You need to do a lot of things to get it to be happy so let&#8217;s step through them all rather than have you hunt for the secret sauce like I did today. First, you&#8217;ll [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re looking to use Eclipse as a debugger for your Perl scripts things can get a bit hairy quickly.  You need to do a lot of things to get it to be happy so let&#8217;s step through them all rather than have you hunt for the secret sauce like I did today.</p>
<p>First, you&#8217;ll want to <a href="http://www.epic-ide.org/download.php" target="_blank">add the EPIC (Eclipse Perl Integration Component) as described on the EPIC site</a>.  That will add support for creating Perl projects, syntax highlighting, and all that.</p>
<p>Next, set a breakpoint in one of your Perl scripts and try to debug it.  If you&#8217;re unlucky you may get one of two error messages.  One error message wants you to install <a href="http://search.cpan.org/~robin/PadWalker-1.93/PadWalker.pm" target="_blank">PadWalker</a> which is a Perl module that handles all of the debugging niceties for Eclipse.  To install that you can either use CPAN or apt.  Using apt is as simple as:</p>
<pre class="syntax bash">sudo apt-get install libpadwalker-perl</pre>
<p>Once you install PadWalker restart Perl and try to debug one of your scripts again.  If it works, you&#8217;re set.  The second possible error message is below&#8230;</p>
<p>Now, you&#8217;ve come all this way and it still doesn&#8217;t work.  You&#8217;ve probably received an error message like this:</p>
<pre class="syntax java">Could not create the view: Plug-in &quot;org.eclipse.debug.ui&quot; was unable to instantiate class &quot;org.eclipse.debug.internal.ui.views.variables.VariablesView&quot;.</pre>
<p>If you dig deeper you&#8217;ll see errors like this:</p>
<pre class="syntax java">java.lang.ClassCircularityError: org/eclipse/debug/internal/ui/DebugUIPlugin</pre>
<p>And if you dig <i>even</i> deeper you&#8217;ll see errors like this:</p>
<pre class="syntax java">Conflict for 'org.epic.perleditor.commands.clearMarker'</pre>
<p>The fix for this was tricky to figure out so just follow these steps:</p>
<ol>
<li>Close Eclipse</li>
<li>Uninstall libpadwalker-perl by running
<pre class="syntax bash">sudo apt-get remove --purge libpadwalker-perl</pre>
</li>
<li>Restart Eclipse and try to set a breakpoint in a Perl script, it should fail (no breakpoint should appear)</li>
<li>Close Eclipse</li>
<li>Reinstall libpadwalker-perl by running
<pre class="syntax bash">sudo apt-get install libpadwalker-perl</pre>
</li>
<li>Restart Eclipse, set a breakpoint, and start debugging again</li>
</ol>
<p>At this point the variables and breakpoints should always work.  Unfortunately the expressions panel will not.  It looks like this is not supported in EPIC just yet.  But, in any case, you now have a full fledged Perl debugger so you can (mostly) stop using print statements to debug your code post mortem.</p>
<p>There are some quirks to note:</p>
<ol>
<li>&#8220;Step Over&#8221; (typically F6) does not work as expected and will step into modules.  If &#8220;Step Return&#8221; worked this wouldn&#8217;t be a problem but it doesn&#8217;t (see the next bullet point).  In this case if you are trying to step over a module you may have to back out and set a breakpoint where the execution will return to the script you want to debug.</li>
<li>&#8220;Step Return&#8221; (typically F7) does not work as expected.  It will usually run until your script ends or hits a breakpoint.</li>
<li>The console window will not let you run arbitrary Perl code so it&#8217;s not a simple replacement for the expressions panel</li>
<li>Perl modules (files with a .pm extension) may not appear with syntax highlighting enabled.  If you are debugging Perl modules you may want to retool your setup and run the module as a Perl script OR have Perl load your module from a file with a .pl extension.</li>
</ol>
<p>Good luck.  Now clean up/fix that Perl code and post in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/03/14/how-to-install-perl-debugging-in-eclipse-on-debian-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tip: Getting the right static imports necessary for basic JUnit testing</title>
		<link>http://blog.timmattison.com/archives/2012/03/02/tip-getting-the-right-static-imports-necessary-for-basic-junit-testing/</link>
		<comments>http://blog.timmattison.com/archives/2012/03/02/tip-getting-the-right-static-imports-necessary-for-basic-junit-testing/#comments</comments>
		<pubDate>Fri, 02 Mar 2012 13:02:47 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=699</guid>
		<description><![CDATA[I&#8217;ve written plenty of JUnit tests in the past but usually I&#8217;m building onto an existing codebase of tests. In the past few days I&#8217;ve been playing around with Unicode and wanted to copy a code snippet from a Hadoop book to see how everything looks in the debugger. When I entered the code I [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written plenty of JUnit tests in the past but usually I&#8217;m building onto an existing codebase of tests.  In the past few days I&#8217;ve been playing around with Unicode and wanted to copy a code snippet from a Hadoop book to see how everything looks in the debugger.  When I entered the code I realized that I was missing some methods that I needed to complete the tests.</p>
<p>Specifically I was trying to use assertThat() and is() but didn&#8217;t know where to find them.  After a bit of Googling I found the two static imports that I needed to copy the code without qualifying assertThat() as Assert.assertThat() and the same goes for is().  They are:</p>
<pre class="syntax java">
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
</pre>
<p>I have to admit that org.hamcrest is a bit less obvious than I would have liked.  <img src='http://blog.timmattison.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/03/02/tip-getting-the-right-static-imports-necessary-for-basic-junit-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tip: A quick primer on waiting on multiple threads in Java</title>
		<link>http://blog.timmattison.com/archives/2012/02/28/tip-a-quick-primer-on-waiting-on-multiple-threads-in-java/</link>
		<comments>http://blog.timmattison.com/archives/2012/02/28/tip-a-quick-primer-on-waiting-on-multiple-threads-in-java/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 21:32:21 +0000</pubDate>
		<dc:creator>Tim Mattison</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.timmattison.com/?p=697</guid>
		<description><![CDATA[Last night I was writing some code to do some performance testing on HDFS. I noticed that single threaded performance wasn&#8217;t anywhere near as good as I expected and my CPUs were spending most of their time idle. I decided to add some threads into the process to see if a multi-threaded speed test would [...]]]></description>
			<content:encoded><![CDATA[<p>Last night I was writing some code to do some performance testing on HDFS.  I noticed that single threaded performance wasn&#8217;t anywhere near as good as I expected and my CPUs were spending most of their time idle.  I decided to add some threads into the process to see if a multi-threaded speed test would consume some of that idle CPU.  It worked as expected so I figured I would share some basic knowledge on how to I started up multiple threads, had them do their work, waited for them to finish without polling, and then recorded the total duration to calculate my statistics.</p>
<p>What you&#8217;ll need to do first is decide what you want to do in the processing thread.  This code will go into a Java Runnable like this:</p>
<pre class="syntax java">
Runnable runnable = new Runnable() {
	@Override
	public void run() {
		// Do something exciting here
	}
};
</pre>
<p>Next you&#8217;ll need to decide how many threads you want to run.  If you wanted to run four threads you could do this:</p>
<pre class="syntax java">
int threadCount = 4;

for (int threadLoop = 0; threadLoop &lt; threadCount; threadLoop++) {
	// XXX - Put the runnable block from above right here

	// Create a new thread
	Thread thread = new Thread(runnable);

	// Add the thread to our thread list
	threads.add(thread);

	// Start the thread
	thread.start();
}
</pre>
<p>That will start four threads.  It&#8217;s best to use a variable so you can update it and use it in other places like calculating your statistics.  Now let&#8217;s wait for all the threads to finish:</p>
<pre class="syntax java">
// Loop through the threads
for (Thread thread : threads) {
	try {
		// Wait for this thread to die
		thread.join();
	} catch (InterruptedException e) {
		// Ignore this but print a stack trace
		e.printStackTrace();
	}
}
</pre>
<p>Finally, you&#8217;ll want to time all of this.  I do something very simple here.  Before all of the code I do this:</p>
<pre class="syntax java">
long startTime = new Date().getTime();
</pre>
<p>After all of the code I do this:</p>
<pre class="syntax java">
long endTime = new Date().getTime();
long durationInMilliseconds = endTime - startTime;
</pre>
<p>With all of that in place you can now measure how long your code ran and then calculate important metrics about it.  For example, if this code did 10,000 operations per thread and ran with 4 threads you would then take the duration and divide that by 40,000 and you&#8217;d get an idea of how many milliseconds it took per operation.  Just make sure you use doubles or you&#8217;ll lose all of your precision due to coercion.  Do this (assuming that your number of operations is stored in a variable called &#8220;operations&#8221;):</p>
<pre class="syntax java">
double millisecondsPerOperation = (double) durationInMilliseconds / (double) operations;
double operationsPerMillisecond = (double) operations / (double) durationInMilliseconds;
</pre>
<p>These are just reciprocals of each other but sometimes one value is a lot easier to understand than the other so I usually calculate them both.</p>
<p>Now that you have those statistics you can try different thread counts, optimize code/loops, etc.  Good luck!  Post in the comments with any ideas and/or issues.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.timmattison.com/archives/2012/02/28/tip-a-quick-primer-on-waiting-on-multiple-threads-in-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

