<?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>John of All Trades &#187; Hacks</title>
	<atom:link href="http://www.johnofalltrades.name/category/hacks/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.johnofalltrades.name</link>
	<description>Yeah. I&#039;d hack that.</description>
	<lastBuildDate>Tue, 26 Apr 2011 17:09:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Nexus Development Hint: Debug a Missing Plugin Resource</title>
		<link>http://www.johnofalltrades.name/2010/03/18/nexus-development-hint-debug-a-missing-plugin-resource/</link>
		<comments>http://www.johnofalltrades.name/2010/03/18/nexus-development-hint-debug-a-missing-plugin-resource/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 23:34:22 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Nexus]]></category>

		<guid isPermaLink="false">http://www.johnofalltrades.name/?p=172</guid>
		<description><![CDATA[To counter-balance my rant the other day about plugin development (specifically in Nexus), I thought I&#8217;d offer a method I developed for coping with the hidden errors I ran into. NOTE: Before I start, I should mention that most of the pain I&#8217;m about to describe, along the method of finding and working around the [...]]]></description>
			<content:encoded><![CDATA[<p>To counter-balance my <a href="http://www.johnofalltrades.name/2010/03/16/the-pain-of-plugin-development/"><img style="border: 0pt none; width: 0pt; height: 0pt; display: none;" src="http://tokentracker.com/token.gif?id=abIe2dd40" alt="" />rant</a> the other day about plugin development (specifically in Nexus), I thought I&#8217;d offer a method I developed for coping with the hidden errors I ran into.</p>
<p><strong>NOTE:</strong> Before I start, I should mention that most of the pain I&#8217;m about to describe, along the method of finding and working around the problem, will soon be a thing of the past. I&#8217;ve spoken to some of the Nexus team members, and they assure me they&#8217;re preparing to move Nexus off of Plexus, and onto Guice for dependency injection. So, once Nexus 1.6.0 comes out <em>[I hope]</em> it&#8217;ll be time to scrap these instructions.</p>
<h2>First, a little background.</h2>
<p>I&#8217;ve developed two Nexus plugins now, both small, and in each case I&#8217;ve run into strange behavior where my custom REST resources would go missing with nary an error to the console or logs. After specifying a particular resource URI, I&#8217;d build and deploy the plugin to my local Nexus instance, then try to hit it using <code>curl</code> with something like the following:</p>
<blockquote><p><code>curl --include --basic -H 'Accept: application/json' http://admin:admin123@localhost:8081/nexus/service/local/echo</code></p></blockquote>
<p>If all was well, the resource should respond with some result, throw an error, or something. But all I received was a 404 Not Found for my trouble. I attempted to dial up the log-level in <code>sonatype-work/nexus/conf/log4j.properties</code>, and scanned both <code>nexus-webapp-1.5.0/logs/wrapper.log</code> <strong>and</strong> <code>sonatype-work/nexus/logs/nexus.log</code> (the location I told log4j to use via a FileAppender). Nada.</p>
<p>When I developed my first plugin, this was the point where I started to bang my head against the wall in earnest. I couldn&#8217;t see any problems, it appeared from the logs that my plugin <strong>was</strong> loaded (it was listed in the plugin-manager output for my plugin bundle), and yet <code>curl</code> doesn&#8217;t lie. After about ten hours of remote debugging, I found a breakpoint that let me see what was going on. Eventually, I found a way to code around the problem, commented the hack liberally in my own code, filed a JIRA (<a href="https://issues.sonatype.org/browse/NEXUS-3308">NEXUS-3308</a>), and moved on. Unfortunately, when it came time to test the second plugin, I&#8217;d already dumped all the old debug breakpoints from the first go-round. So, this time I&#8217;m going to document the setup I used to find and fix the problem before I forget it again.</p>
<h2>Prepare your Nexus instance.</h2>
<p>Before we even talk about remote debugging from Eclipse, we need to setup Nexus to listen on a JPDA (java debugger) port. To do this, I modified the stock Java Service Wrapper <code>wrapper.conf</code> file that comes with Nexus as follows:</p>
<p><a href="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-wrapper.png"><img src="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-wrapper.png" alt="" width="501" height="263" /></a></p>
<p>You&#8217;ll notice that I actually have two variants of this JPDA configuration: one with <code>suspend=y</code>, and one with <code>suspend=n</code>. In most of my previous experience with remote debugging, I&#8217;ve been starting the application with the debugger attached so I can catch boot errors, things like that. But in the case of Nexus, I almost never use the <code>suspend=y</code> approach, since this makes the whole startup process excruciatingly slow. It&#8217;s not Nexus&#8217; fault, it&#8217;s just what happens when your remote debugger is watching Every. Single. Line. If you&#8217;re even halfway paying attention, you should have no problem watching the logs and attaching your remote debugger in plenty of time to catch the breakpoint you&#8217;re interested in. Particularly if it&#8217;s the breakpoint I&#8217;ll discuss below.</p>
<p>Now that you have Nexus rigged for debugging, let&#8217;s talk about the remote debugger before we restart. Once we restart Nexus, we&#8217;ll need to be on the ball to attach the debugger and intercept our breakpoint of choice at boot.</p>
<h2>Setup your remote debugger.</h2>
<p>What follows is described in terms of Eclipse. It&#8217;s the IDE I use, for a number of reasons. I get endless shit about this from the IDEA fanatics I run into here and there. For those people: I understand you&#8217;re probably of above-average intelligence. You will probably have no problem at all translating my instructions into IDEA-ese.</p>
<p>To start, get the project setup so you can actually navigate something meaningful with your debugger. This means attaching the sources for the <code>plexus-container-default</code> dependency in your project. I&#8217;m using <a href="http://m2eclipse.sonatype.org/">m2eclipse</a>, which makes it pretty easy. The following is a view of my Package Explorer, poised to go download and attach the Plexus source code:</p>
<p><a href="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-src.png"><img src="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-src.png" alt="" width="371" height="413" /></a></p>
<p>Next, setup a new Debug Configuration for your remote Nexus instance. This is pretty straightforward; the main points to notice is that your plugin project is selected as the main entry point, the host is set to <code>localhost</code> (or, wherever your Nexus instance is running), and the port is set to <code>8000</code> (this must correspond with the <code>wrapper.conf</code> modifications above). Your configuration should look something like this:</p>
<p><a href="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-remote.png"><img src="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-remote.png" alt="" width="480" height="384" /></a></p>
<p>Now we&#8217;re ready to configure that critical breakpoint, and setup our debugging environment so we can see the output. To set the breakpoint, I navigated through the <code>plexus-container-default</code> artifact until I found <code>org.codehaus.plexus.component.collections.AbstractComponentCollection</code>, scrolled to <strong>line 159</strong>, and set the breakpoint, like so:</p>
<p><a href="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-debug-breakpoint.png"><img src="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-debug-breakpoint.png" alt="" width="683" height="352" /></a></p>
<p><em>(You can set this breakpoint easily by double-clicking in the left gutter on line 159.)</em> Also, notice that the breakpoint shows up in my Breakpoints View, in the upper-right corner. If you read <strong>NEXUS-3308</strong>, you&#8217;ll understand why this particular breakpoint is so critical&#8230;</p>
<p>Once you&#8217;ve set the breakpoint, also setup a watched expression to output the full exception stacktrace. To do this, right-click in the <strong>Watched Expressions View</strong>, and select <strong>Add Watched Expression</strong>. Then, enter the following:</p>
<p><a href="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-expr2.png"><img src="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-expr2.png" alt="" width="356" height="208" /></a></p>
<p>Finally, since the result of that watched expression will be quite verbose, it&#8217;s important to extend the maximum buffer for the output pane in the Watched Expression View. To avoid having to do this twice, I&#8217;ve set mine to <code>0</code> <em>(no maximum)</em>. Just select <strong>Max Length&#8230;</strong> from the following menu, and set it appropriately:</p>
<p><a href="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-expr.png"><img src="http://www.johnofalltrades.name/wp-content/uploads/2010/03/nexus-plugin-dev-expr.png" alt="" width="270" height="283" /></a></p>
<h2>Debug!</h2>
<p>Now, we&#8217;re ready to dig in and find that elusive bug that&#8217;s been making life hell. To do this, you&#8217;re going to be paying attention!</p>
<p>Ready? Okay, first stop Nexus and then re-run it in console mode. This allows you to stop it with CTL-C after you&#8217;re done debugging. The commands look something like this:</p>
<blockquote><p><code><br />
~/apps/nexus/current/bin/jsw/macosx-universal-32/nexus stop<br />
~/apps/nexus/current/bin/jsw/macosx-universal-32/nexus console<br />
</code></p></blockquote>
<p><strong>As soon as you see output like the following</strong>, attach your remote debugger:</p>
<pre>INFO   | jvm 1    | 2010/03/16 17:22:30 | Initializing Nexus (OSS), Version 1.5.0
</pre>
<p>Now, simply wait. If your Nexus component is failing when it initializes, the breakpoint will halt the system and the watched expression above will contain the full stacktrace. If you click on that watched expression, then click on the output pane, you can use CTL-A (CMD-A), CTL-C (CMD-C) to Select All of the stacktrace, then Copy it to your clipboard. From here, I&#8217;ve had a lot of luck opening Any Old Text Editor and pasting the stacktrace there for perusal. You can now detach the debugger (the button that looks like an electrical &#8216;N&#8217;) and let Nexus finish booting, or hit the continue button (looks like a pause/play button on a DVD player) to set a course for the next failing component.</p>
<p><strong>One word of warning:</strong> if you take your sweet time here, you&#8217;ll miss your chance. This is because the default startup timeout for the Java Service Wrapper in Nexus is 90 seconds. If you take longer than about 30-45 seconds poking through running code, Java Service Wrapper will kill the process. Of course, if you really <strong>have</strong> to have extra time, that&#8217;s configurable too.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.johnofalltrades.name%2F2010%2F03%2F18%2Fnexus-development-hint-debug-a-missing-plugin-resource%2F&amp;title=Nexus%20Development%20Hint%3A%20Debug%20a%20Missing%20Plugin%20Resource" id="wpa2a_2"><img src="http://www.johnofalltrades.name/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.johnofalltrades.name/2010/03/18/nexus-development-hint-debug-a-missing-plugin-resource/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On Moving to WordPress from Pebble</title>
		<link>http://www.johnofalltrades.name/2009/12/01/on-moving-to-wordpress-from-pebble/</link>
		<comments>http://www.johnofalltrades.name/2009/12/01/on-moving-to-wordpress-from-pebble/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 03:30:26 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[pebble]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.johnofalltrades.name/?p=140</guid>
		<description><![CDATA[So, you may have noticed that I recently migrated this blog from Pebble to WordPress. Actually, I migrated two former Pebble blogs, plus one former WordPress blog, to this new one. The WP install was simple, and so was the transfer of blog entries from one WP instance to another. Migrating from Pebble was a [...]]]></description>
			<content:encoded><![CDATA[<p><img style="border: 0pt none; width: 0pt; height: 0pt; display: none;" src="http://tokentracker.com/token.gif?id=35I178ndf" alt="" />So, you may have noticed that I recently migrated this blog from Pebble to WordPress. Actually, I migrated <i>two</i> former Pebble blogs, plus one former WordPress blog, to this new one. The WP install was simple, and so was the transfer of blog entries from one WP instance to another. Migrating from Pebble was a little more challenging, particularly since I had a lot of posts that I didn&#8217;t want to handle manually.</p>
<p>I started out by looking at the <b><a href="http://code.google.com/p/pebble2wordpress/">Pebble2Wordpress</a></b> importer code, which is written in Ruby. (I first found a reference to this project from <b><a href="http://www.spritle.com/blogs/?p=107#more-107">The Spritle Blog</a></b> blog post, which has some more information about how it&#8217;s meant to be used.) I selected this project in particular because it&#8217;s written in a language I can fine tune as needed.</p>
<p>I&#8217;m not sure whether this project ever really worked as-is out of the source repository, but I can say for sure that it didn&#8217;t work for me using the instructions provided on the blog post. In an attempt to understand where the developer was coming from, and determine whether I could cobble together something to work for my own particular migration, I dug into the source. What I found seemed pretty overwrought and confusing, particularly for something that amounts to a simple migration script to morph XML documents into DB calls (not something that will ever attract a huge user base). After refactoring the code to provide minimal error handling, and to inline all class definitions into one ruby script alongside the code that uses these classes, I thought I had something understandable to start testing.</p>
<p>The general approach of the code is to create ActiveRecord representations for terms (read: categories), term-post relationships, posts, and comments. Once the database is connected, the script iterates through all <b><code>*.xml</code></b> files in the inputXML directory, and parses the Pebble XML format into Post/Comment/Category instances which are then saved into the WP database. During the parsing process, certain things like image URLs are massaged from the old Pebble layout to something more compatible with WP. Since the default WP uploads directory has the date baked into the file path, I opted to simplify things and put all migrated files into the <b><code>uploads/</code></b> base directory. This has an added benefit of giving me one-stop shopping for anything that breaks during the migration process, instead of picking over a nested directory structure.</p>
<p>Before you can start using the code, you&#8217;ll need to install some RubyGems and OS hooks:</p>
<pre class="brush: bash; title: ; notranslate">
$  sudo apt-get -y install rubygems mysql-dev
...
$  gem install activerecord activerecord-jdbcmysql-adapter
...
</pre>
<p>Next, you need to create a new directory alongside the <b><code>convert.rb</code></b> script, called <b><code>inputXML/</code></b>. Into this you should copy all of the XML files from the pebble data directory. My data directory was in <b><code>/opt/web/sites/ejlife.net/var/pebble/blogs/buildchimp/</code></b>, so I used the following commands to achieve this:</p>
<pre class="brush: bash; title: ; notranslate">
$ find /opt/web/sites/ejlife.net/var/pebble/blogs/buildchimp/2009 -type f -name '*.xml' -exec cp '{}' inputXML/ \;
...
$ find /opt/web/sites/ejlife.net/var/pebble/blogs/buildchimp/2008 -type f -name '*.xml' -exec cp '{}' inputXML/ \;
...
$ find /opt/web/sites/ejlife.net/var/pebble/blogs/buildchimp/2007 -type f -name '*.xml' -exec cp '{}' inputXML/ \;
...
$ find /opt/web/sites/ejlife.net/var/pebble/blogs/buildchimp/2006 -type f -name '*.xml' -exec cp '{}' inputXML/ \;
</pre>
<p>I know, using some more arcane shell-fu I could have combined the individual commands into one. However, rather than take a chance of fouling something up with an overly-complex command line, I chose to use the Base arrow-up feature to retrieve and modify my previous command. Simple, effective, and nearly fool-proof.</p>
<p>Luckily, in my case I had a bare WP install that I could abuse a bit while I fine tuned the migration code. Along with a decent database client (I <b>love</b> the free version of <b><a href="http://www.minq.se/products/dbvis/">DBVisualizer</a></b> for this), rolling back failed migrations are a breeze. After a failed migration attempt, I simply issued the following SQL commands to get back near enough to the base install:</p>
<pre class="brush: sql; title: ; notranslate">
DELETE FROM wp_posts;

DELETE FROM wp_comments;

DELETE FROM wp_term_relationships WHERE object_id $  999
</pre>
<p><b>NOTE:</b> I chose to delete term relationships where the object ID is 1000 or greater, since it seems like the auto-increment field for posts starts at around 1000. This may not be the case in all environments.</p>
<p>I&#8217;m not going to pollute this blog post by giving a full listing of the migration script, but you can download it here: <b><a href="/wp-content/uploads/src/pebble2wordpress/convert.rb">convert.rb</a></b>. It has an accompanying database configuration YAML file that looks like this: <b><a href="/wp-content/uploads/src/pebble2wordpress/database.yml">database.yml</a></b>. The script expects the <b><code>inputXML/</code></b> directory and the <b><code>database.yml</code></b> file to be in the same directory as the script itself. Use the script if you want to, enjoy it, but above all, <i>DON&#8217;T BLAME ME IF YOU BLOW SOMETHING UP</i>.</p>
<p>I then tested, rinsed, and repeated until I was pleased with the result. As a final step, I copied the contents of the <b><code>files/</code></b> and <b><code>images/</code></b> directories from the Pebble data directory into my WP install:</p>
<pre class="brush: bash; title: ; notranslate">
$  cp -rf /opt/web/sites/ejlife.net/var/pebble/blogs/buildchimp/images/* /opt/web/sites/johnofalltrades.name/htdocs/wp-content/uploads
...
$  cp -rf /opt/web/sites/ejlife.net/var/pebble/blogs/buildchimp/files/* /opt/web/sites/johnofalltrades.name/htdocs/wp-content/uploads
...
</pre>
<p>That&#8217;s about all there is to it. Hackish? Maybe. Effective? Definitely. I&#8217;m very happy in my new WordPress digs!</p>
<p><b>UPDATE:</b> I&#8217;ve submitted my changes back to the project in <b><a href="http://code.google.com/p/pebble2wordpress/issues/detail?id=1">this issue</a></b>.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.johnofalltrades.name%2F2009%2F12%2F01%2Fon-moving-to-wordpress-from-pebble%2F&amp;title=On%20Moving%20to%20WordPress%20from%20Pebble" id="wpa2a_4"><img src="http://www.johnofalltrades.name/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.johnofalltrades.name/2009/12/01/on-moving-to-wordpress-from-pebble/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

