<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Benjamin McCann - Development Blog</title>
	
	<link>http://www.benmccann.com/dev-blog</link>
	<description>The software development weblog of Benjamin McCann.</description>
	<lastBuildDate>Sun, 29 Aug 2010 17:40:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/benmccann-tech" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="benmccann-tech" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">benmccann-tech</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Creating .asc signature files with GPG</title>
		<link>http://www.benmccann.com/dev-blog/creating-asc-signature-files-with-gpg/</link>
		<comments>http://www.benmccann.com/dev-blog/creating-asc-signature-files-with-gpg/#comments</comments>
		<pubDate>Mon, 02 Aug 2010 03:35:34 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=329</guid>
		<description><![CDATA[First create a key: gpg --gen-key And upload it to a public key server: gpg --keyserver hkp://pgp.mit.edu --send-keys &#60;keyid&#62; Where &#60;keyid&#62; is retrieved from: gpg --list-keys Then generate your key: gpg -ab &#60;filename&#62; More details available on Maven&#8217;s how to generate PGP signatures page.]]></description>
			<content:encoded><![CDATA[<p>First create a key:<br />
<code>gpg --gen-key</code></p>
<p>And upload it to a public key server:<br />
<code>gpg --keyserver hkp://pgp.mit.edu --send-keys &lt;keyid&gt;</code></p>
<p>Where &lt;keyid&gt; is retrieved from:<br />
<code>gpg --list-keys</code></p>
<p>Then generate your key:<br />
<code>gpg -ab &lt;filename&gt;</code></p>
<p>More details available on <a href="https://docs.sonatype.org/display/Repository/How+To+Generate+PGP+Signatures+With+Maven">Maven&#8217;s how to generate PGP signatures page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/creating-asc-signature-files-with-gpg/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting started with R</title>
		<link>http://www.benmccann.com/dev-blog/getting-started-with-r/</link>
		<comments>http://www.benmccann.com/dev-blog/getting-started-with-r/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 06:03:40 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[R]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=313</guid>
		<description><![CDATA[Getting Help R is incredibly frustrating to learn because it is impossible to do a Google search and have anything meaningful come back for the query &#8220;R&#8221;.   RSeek may provide some help in this regard. Installing Libraries To use R in Linux, I recommend installing the latest version of the RKWard GUI program. As [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Getting Help</strong></p>
<p>R is incredibly frustrating to learn because it is impossible to do a Google search and have anything meaningful come back for the query &#8220;R&#8221;.   <a href="http://www.rseek.org/">RSeek</a> may provide some help in this regard.</p>
<p><strong>Installing Libraries</strong></p>
<p>To use R in Linux, I recommend <a href="http://sourceforge.net/apps/mediawiki/rkward/index.php?title=Binaries_and_Build_Scripts#Unofficial_Ubuntu_repositories">installing the latest version of the RKWard GUI program</a>.</p>
<p>As an example here we&#8217;ll display a stock chart using the quantmod library.  To install a library run <em><a href="http://stat.ethz.ch/R-manual/R-devel/library/utils/html/install.packages.html">install.packages</a></em>:</p>
<pre><code>install.packages("quantstrat", repos="http://R-Forge.R-project.org", type="source")</code></pre>
<p>In the code above c is used to combine arguments into a list and is a very common R command.  You&#8217;ll also notice the use of repos to specify a named argument.</p>
<p>You can install packages from source if needed:</p>
<pre><code>install.packages("xtime", lib="/home/bmccann/R/i486-pc-linux-gnu-library/2.10", repos = NULL, type="source")
install.packages("xts", lib="/home/bmccann/R/i486-pc-linux-gnu-library/2.10", repos = NULL, type="source")</code></pre>
<p>You can also update packages as needed.  Note that this will not work from RKWard because you need administrative permissions, so you should do it from the command line:</p>
<pre><code>sudo R
update.packages()
q()</code></pre>
<p>In order to load any libraries that you&#8217;ve installed, you&#8217;ll need to run <em><a href="http://stat.ethz.ch/R-manual/R-devel/library/base/html/library.html">library</a></em>:</p>
<pre><code># load the quantmod library
library(quantmod)
library(TTR)
library(blotter)
library(PerformanceAnalytics)
library(FinancialInstrument)

# get the S&amp;P 500 data from Yahoo!
getSymbols("^GSPC", from = "1900-01-01", to = Sys.Date())

# chart the past 5 years of the S&amp;P 500 with 50-day SMA
chartSeries(GSPC, TA="addSMA(n = 50)", subset='last 5 years', theme='white')

# chart the past 5 years of the S&amp;P 500 with 200 and 300 day SMA
sma200&lt;-SMA(close, n=200)
sma300&lt;-SMA(close, n=300)
chartSeries(close, subset='last 5 years', theme='white')
addTA(sma200, on = 1, col=c('red','red'))
addTA(sma300, on = 1, col=c('blue','blue'))

# 50-day SMA in a more manual fashion to demonstrate adding custom lines to chart
close&lt;-Cl(GSPC)
sma&lt;-SMA(close, n=50)
chartSeries(close, subset='last 5 years', theme='white')
addTA(sma, on = 1, col=c('red','red'))

# Reset the workspace
rm(list=ls(all=TRUE, pos=.blotter), pos=.blotter)
rm(list=ls(all=TRUE, pos=.instrument), pos=.instrument)</code></pre>
<p><strong>Performance Problems</strong></p>
<p>You may notice that performance is harder to get right in R.  The standard for-loop solutions used in other languages are very inefficient in R and should be vectorized.  This <a href="http://stackoverflow.com/questions/2908822/speed-up-the-loop-operation-in-r">Stack Overflow discussion</a> gives some insight into R performance problems.  You can time you code by surrounding it with <em>system.time</em>:</p>
<pre><code>time &lt;- system.time({
  # code here
})
print(paste("The code took", time["elapsed"], "seconds."))</code></pre>
<p><strong>Testing</strong></p>
<p>RUnit is helpful in testing R code.  I wrote an <a href="https://r-forge.r-project.org/scm/viewvc.php/pkg/blotter/tests/testSuite.R?view=markup&amp;root=blotter">RUnit test suite for blotter</a>, which may be a helpful example.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/getting-started-with-r/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing Evan’s Debugger in Ubuntu</title>
		<link>http://www.benmccann.com/dev-blog/installing-evans-debugger-in-ubuntu/</link>
		<comments>http://www.benmccann.com/dev-blog/installing-evans-debugger-in-ubuntu/#comments</comments>
		<pubDate>Mon, 28 Jun 2010 00:31:28 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=287</guid>
		<description><![CDATA[Evan&#8217;s Debugger is a Linux replacement for OllyDbg. You can install it by downloading the .tar.gz and doing the following: $ sudo apt-get install libqt4-dev $ sudo apt-get install libboost1.40-all-dev $ tar zxvf debugger-0.9.15.tgz $ mv debugger /usr/local/src/ $ cd /usr/local/src/debugger $ qmake -makefile DEFAULT_PLUGIN_PATH="/usr/lib/edb/" $ make $ sudo make INSTALL_ROOT=/usr install]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.codef00.com/projects.php#Debugger">Evan&#8217;s Debugger</a> is a Linux replacement for <a href="http://www.ollydbg.de/">OllyDbg</a>.</p>
<p>You can install it by downloading the .tar.gz and doing the following:<br />
<code> </code></p>
<p><code></p>
<pre>$ sudo apt-get install libqt4-dev
$ sudo apt-get install libboost1.40-all-dev
$ tar zxvf debugger-0.9.15.tgz
$ mv debugger /usr/local/src/
$ cd /usr/local/src/debugger
$ qmake -makefile DEFAULT_PLUGIN_PATH="/usr/lib/edb/"
$ make
$ sudo make INSTALL_ROOT=/usr install
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/installing-evans-debugger-in-ubuntu/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>My first experience with Ubuntu</title>
		<link>http://www.benmccann.com/dev-blog/my-first-experience-with-ubuntu/</link>
		<comments>http://www.benmccann.com/dev-blog/my-first-experience-with-ubuntu/#comments</comments>
		<pubDate>Sun, 27 Jun 2010 02:08:50 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=277</guid>
		<description><![CDATA[I just got a laptop loaded with Lucid Lynx and have had a bit of a mixed experience adjusting.  I&#8217;ve actually used Ubuntu a bit in the past, but only minimally and never as my primary computer until now. First reactions I like the default background. Have the fonts improved?  Fonts have always looked bad [...]]]></description>
			<content:encoded><![CDATA[<p>I just got a laptop loaded with Lucid Lynx and have had a bit of a mixed experience adjusting.  I&#8217;ve actually used Ubuntu a bit in the past, but only minimally and never as my primary computer until now.</p>
<p><strong>First reactions</strong></p>
<ul>
<li>I like the default background.</li>
<li>Have the fonts improved?  Fonts have always looked bad on Linux distros I&#8217;ve used in the past, but the Ubuntu font seems to be pretty clear.</li>
<li>Why is the window close button in the top left?  Every computer I&#8217;ve ever used it&#8217;s been in the top right.  I hate that its anywhere else in Ubuntu.  It&#8217;s annoying because it goes against convention.  It&#8217;s also frustrating because it&#8217;s not uniform.  E.g. when closing tabs or windows in Chrome, the x is still in the top right.</li>
<li>I&#8217;m going to have to get used to the menu bar being on the top as opposed to being on the bottom on XP.  I think I like the change though.</li>
<li>OMG.  Why is it so hard to change anything on the menu bar?  To move anything I have to right click every single icon on the menu bar and uncheck &#8220;Lock to Panel&#8221;.  Then I need to specifically select the Move option to be able to move the icon.  It&#8217;s very annoying that this is so difficult.  A much better UI would be a global lock/unlock for the panel instead of the per-icon mechanism and drag and drop support without having to first go into move mode.</li>
<li>Finally!!!  You fixed the menus!!  The menus in every other Linux distro I&#8217;ve ever used have been super cluttered and unorganized.  I LOVE that they don&#8217;t suck anymore.  Do not underestimate how important this is.</li>
<li>The menus themselves are even harder to change than the menu bar.  I had to do a Google search to figure it out.  Who was the genius that decided you need to go to System &gt; Preferences &gt; Main Menu?  Why the hell can&#8217;t I just drag icons and around and right click icons to edit their properties?</li>
</ul>
<p><strong>Nice surprises</strong></p>
<ul>
<li>The pop up that appears when you change the volume or connect to Wi-Fi is beautiful and super friendly.  This is the one place where usability is hands down better than XP!  The volume bars in XP were really ugly.  And I hated having to x out of the Wi-Fi connection pop-up in XP.  The Ubuntu one nicely fades out after a second or so.  Kudos to that UI designer.  Can he be in charge of the rest of the UI?</li>
<li>Wow does the Wi-Fi connect fast after startup</li>
<li>Making Windows+L lock the screen on my computer was surprisingly easy.  The Keyboard Shortcuts window itself was really difficult to use, but I was really happy how easy it was to find.</li>
<li><a href="http://www.hulu.com/labs/hulu-desktop-linux">Hulu Desktop</a> is a savior.  It kept me from defenestrating my computer when the website was totally broken in Linux.</li>
<li>I was able to use <a href="http://keepass.info/">KeePass 2.x</a> eventhough it&#8217;s a Windows program.  I just needed to install libmono-winforms2.0-cil and xdotool.  No I can type &#8220;mono KeyPass.exe&#8221; to run the program.  Awesome!</li>
<li>I was able to run Internet Explorer fairly easily by using <a href="http://www.playonlinux.com">PlayOnLinux</a></li>
</ul>
<p><strong>Frustrations</strong></p>
<ul>
<li><strong><span style="font-weight: normal;">Why is there no volume control?!!!</span></strong></li>
<li><strong><span style="font-weight: normal;">Using NX shadowing requires disabling Compiz.</span></strong></li>
<li><strong><span style="font-weight: normal;">The jar command is missing by default (fix with <em>sudo apt-get install openjdk-6-jdk</em>)</span></strong></li>
<li><strong><span style="font-weight: normal;">It seems that by default there is no GUI installed for controlling the firewall in Ubuntu?  Can that really be true?</span></strong></li>
<li><strong><span style="font-weight: normal;"> </span></strong>There are completely different panel buttons for logging out and shutting down.  These two buttons/menus should be merged into one.</li>
<li>I&#8217;m having a lot of trouble renaming mounted network shares so that they show up with a nice name.</li>
<li>It&#8217;d be nice if I didn&#8217;t have to <a href="http://www.chromeextensions.org/appearance-functioning/backspace-as-back-for-linux-2/">install an extension to make backspace work in Chrome</a>.</li>
<li>I wanted to see what Kubuntu was like so I installed KDE.  I&#8217;ve always preferred KDE in the past, but it was just awful on Ubuntu.  The menus were so cluttered I didn&#8217;t know where to go for anything.  When I switched back to Gnome now all of my menus were now cluttered there too with a bunch of KDE crap!  I uninstalled the KDE Plasma Desktop library that I checked to install KDE, but it left all of it&#8217;s dependencies (i.e. everything).  It was quite an ordeal to uninstall.  I uninstalled a couple of the base libraries and that got most the garbage off my system.</li>
</ul>
<p><strong>Nagging throw my chair through the window frustrations</strong></p>
<ul>
<li>Ubuntu has managed to take Flash on Linux to a whole new low.  It works worse than on any other Linux distribution I&#8217;ve ever used, which is saying a lot.  I realize it&#8217;s not totally their fault and hope that this will become a non issue with <a href="http://www.webmproject.org/">WebM</a>, but right now it&#8217;s an enormous frustration.</li>
<li>Please, please, please make Ctrl+Y redo in gedit.  Redo is Ctrl+Y in every other program I use in Ubuntu (Eclipse, Gimp, Chrome, Firefox, Open Office, Scribes, Geany, etc).  If you want to keep Ctrl+Shift+Z as redo that&#8217;s fine, just add a second key binding for Ctrl+Y.  I might have to finally plunk down the money to try the new Linux version of <a href="http://www.ultraedit.com/">UltraEdit</a>.</li>
</ul>
<p><strong>Necessary fixes</strong></p>
<ul>
<li>Put the x, minimize, and maximize buttons back in the top right corner of the windows.  Big thanks to gdi2k for pointing out a <a href="http://pricklytech.wordpress.com/2010/04/30/ubuntu-10-4-lucid-how-to-move-the-minimize-maximize-and-close-buttons-back-to-the-right/">solution</a> in the comments.  I first tried to fix this by changing to a different theme, which solved the problem, but made everything super ugly.</li>
<li>Add a volume slider by adding the &#8220;Notification Area&#8221; to the panel and running <em>gnome-volume-control-applet</em></li>
<li>Get a text editor where Ctrl+Y works.  <a href="http://scribes.sourceforge.net/download.html">Download scribes</a> and then <a href="http://ubuntuforums.org/showthread.php?t=299086">change the default text editor</a>.</li>
</ul>
<p><strong>Installing NX for remote desktop support</strong></p>
<div id="_mcePaste">
<ul>
<li><a href="http://www.nomachine.com/download-package.php?Prod_Id=1978">Download</a> and install the client, node, and server in that order</li>
<li>Run <em>sudo /usr/NX/scripts/setup/nxserver &#8211;install</em></li>
<li>Optional for better security:   Run <em>sudo /usr/NX/bin/nxserver &#8211;keygen. </em>In your NX client, open “Configure…&#8221; &gt; “General&#8221; tab &gt; “Key …&#8221; and copy the contents of “/usr/NX/share/keys/default.id_dsa.key&#8221; into the key window and save it.</li>
<li>Optional for session shadowing:  Open “/usr/NX/etc/server.cfg&#8221;.  Uncomment ‘EnableSessionShadowingAuthorization = “1″ and change the value to “0″.  You can now select “Shadow&#8221; in the client under the General &gt; Desktop if you’d like to do desktop sharing.  You&#8217;ll also need to disable Compiz for this by System &gt; Preferences &gt; Appearance &gt; Visual Effects &gt; None.</li>
</ul>
</div>
<p>Overall I rather like Ubuntu.  <a href="http://www.benmccann.com/dev-blog/opensuse-11-2-setup-and-review/">OpenSUSE 11.2 left me feeling rather frustrated</a>, so I&#8217;ve now switched to Ubuntu on my home machine as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/my-first-experience-with-ubuntu/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Hibernate with JPA Annotations and Guice</title>
		<link>http://www.benmccann.com/dev-blog/hibernate-with-jpa-annotations-and-guice/</link>
		<comments>http://www.benmccann.com/dev-blog/hibernate-with-jpa-annotations-and-guice/#comments</comments>
		<pubDate>Sun, 02 May 2010 05:49:20 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Guice]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Persistence]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=260</guid>
		<description><![CDATA[In this tutorial, I use the H2 database, which you can utilize by downloading the jar or you can replace with your own DB. First off, you need to create a persistence.xml in a folder named META-INF at the root of your classpath. For example, if you&#8217;re using Maven you can create src/main/java/META-INF/persistence.xml. It lists [...]]]></description>
			<content:encoded><![CDATA[<p>In this tutorial, I use the <a href="http://www.h2database.com">H2 database</a>, which you can utilize by downloading the jar or you can replace with your own DB.</p>
<p>First off, you need to create a persistence.xml in a folder named META-INF at the root of your classpath.  For example, if you&#8217;re using <a href="http://maven.apache.org/">Maven</a> you can create src/main/java/META-INF/persistence.xml.  It lists all the classes you want <a href="http://www.hibernate.org/">Hibernate</a> to persist and any other Hibernate properties you might want to specify.  I also define Hibernate properties later on in the tutorial when creating the <a href="http://java.sun.com/javaee/6/docs/api/index.html?javax/persistence/EntityManagerFactory.html">EntityManagerFactory</a>.<br />
<code>
<pre>&lt;persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0"&gt;
  &lt;persistence-unit name="db-manager"&gt;
    &lt;class&gt;com.benmccann.db.ExamplePersistedClass&lt;/class&gt;
    &lt;properties&gt;
      &lt;!-- Disable the second-level cache  --&gt;
      &lt;property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/&gt;

      &lt;!-- Default is false for backwards compatibility.  Should be used on all new projects --&gt;
      &lt;property name="hibernate.id.new_generator_mappings" value="true"/&gt;
    &lt;/properties&gt;
  &lt;/persistence-unit&gt;
&lt;/persistence></pre>
<p></code></p>
<p>We listed the class com.benmccann.db.ExamplePersistedClass as being the only persisted class, so now we&#8217;ll go ahead and create it.  Note that you need a no-argument constructor.  Fields in your bean will be persisted unless annotated with @Transient.  <a href="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/persistent-classes.html">More info about persisted classes is available in the Hibernate documentation</a>.</p>
<p><code>
<pre>package com.benmccann.db;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class ExamplePersistedClass {

  @Id
  @GeneratedValue
  private Long id;

  private String otherField;

  public ExamplePersistedClass() {}

  public void setId(Long id) {
    this.id = id;
  }

  public Long getId() {
    return id;
  }

  public void setOtherField(String otherField) {
    this.otherField = otherField;
  }

  public String getOtherField() {
    return otherField;
  }

}</pre>
<p></code></p>
<p>And we&#8217;ll create a DAO for it:<br />
<code>
<pre>package com.benmccann.db;

import javax.persistence.EntityManager;

public class ExamplePersistedClassDao {

  protected EntityManager entityManager;

  @Inject
  public ExamplePersistedClassDao(EntityManager entityManager) {
    this.entityManager = entityManager;
  }

  public void saveInNewTransaction(ExamplePersistedClass object) {
    entityManager.getTransaction().begin();
    save(object);
    entityManager.getTransaction().commit();
  }

  public void save(ExamplePersistedClass object) {
    entityManager.persist(object);
  }

  public ExamplePersistedClass getByOtherField(String otherField) {
    return (ExamplePersistedClass) entityManager
        .createQuery("select e from ExamplePersistedClass e where e.otherField=:otherField")
        .setParameter("otherField", otherField)
        .getSingleResult();
  }

}
</pre>
<p></code></p>
<p>And finally, we&#8217;ll create a <a href="http://code.google.com/p/google-guice/wiki/GettingStarted">Guice module</a> to define the injection.  Note that EntityManagerFactory is thread-safe while <a href="http://java.sun.com/javaee/6/docs/api/index.html?javax/persistence/EntityManager.html">EntityManager</a> is not.  I use <a href="http://java.sun.com/javase/6/docs/api/index.html?java/lang/ThreadLocal.html">ThreadLocal</a> storage here in order to have one entity manager per thread.  When creating the EntityManagerFactory notice that I use the same &#8220;db-manager&#8221; string that is defined in the persistence.xml file.  Also, I defined most of my Hibernate properties here rather than in the persistence.xml file to demonstrate how you can alter the values of these properties.  For example, when writing tests it could be very helpful to override the connection string to point to a local test database.</p>
<p><code>
<pre>package com.benmccann.db;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;

/**
 * @author Ben McCann (benmccann.com)
 */
public class DbModule extends AbstractModule {

  private static final ThreadLocal<EntityManager> ENTITY_MANAGER_CACHE
      = new ThreadLocal<EntityManager>();

  public void configure() {
  }

  @Provides @Singleton
  public EntityManagerFactory provideEntityManagerFactory() {
    Map<String, String> properties = new HashMap<String, String>();
    properties.put("hibernate.connection.driver_class", "org.h2.Driver");
    properties.put("hibernate.connection.url", "jdbc:h2:test");
    properties.put("hibernate.connection.username", "sa");
    properties.put("hibernate.connection.password", "");
    properties.put("hibernate.connection.pool_size", "1");
    properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
    properties.put("hibernate.hbm2ddl.auto", "create");
    return Persistence.createEntityManagerFactory("db-manager", properties);
  }

  @Provides
  public EntityManager provideEntityManager(EntityManagerFactory entityManagerFactory) {
    EntityManager entityManager = ENTITY_MANAGER_CACHE.get();
    if (entityManager == null) {
      ENTITY_MANAGER_CACHE.set(entityManager = entityManagerFactory.createEntityManager());
    }
    return entityManager;
  }

}</pre>
<p></code></p>
<p>Now we can run our code:<br />
<code>
<pre>package com.benmccann.db;

import java.sql.SQLException;
import java.util.Date;

import org.junit.Assert;
import org.junit.Test;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.benmccann.db.DbModule;
import com.benmccann.db.ExamplePersistedClass;
import com.benmccann.db.ExamplePersistedClassDao;

public class H2DBTest {

  @Test
  public void testDb() throws SQLException {
    Injector injector = Guice.createInjector(new DbModule());
    ExamplePersistedClassDao examplePersistedClassDao = injector.getInstance(ExamplePersistedClassDao.class);   

    ExamplePersistedClass example = new ExamplePersistedClass();
    example.setOtherField("hello world");
    examplePersistedClassDao .saveInNewTransaction(quote);

    ExamplePersistedClass retrieved = examplePersistedClassDao.getByOtherField("hello world");

    Assert.assertEquals(example.getId(), retrieved.getId());
    Assert.assertEquals(example.getOtherField(), retrieved.getOtherField());
  }

}
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/hibernate-with-jpa-annotations-and-guice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trouble Resuming NX Session</title>
		<link>http://www.benmccann.com/dev-blog/trouble-resuming-nx-session/</link>
		<comments>http://www.benmccann.com/dev-blog/trouble-resuming-nx-session/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 04:25:51 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[NX]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=251</guid>
		<description><![CDATA[Resume button disabled I was unable to resume my NX session.  While trying to connect, the resume button was greyed out (or grayed out)  This apparently can happen if the two machines are running at a different color depth. The machine I was trying to connect to was running Ubuntu, so I checked the color [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Resume button disabled</strong></p>
<p>I was unable to resume my NX session.  While trying to connect, the resume button was greyed out (or grayed out)  This apparently can happen if the two machines are running at a different color depth.</p>
<p>The machine I was trying to connect to was running Ubuntu, so I checked the color depth (sudo cat /etc/X11/xorg.conf) and saw that it was running at 24 bit.  Then I checked the color depth on my Windows machine (Control Panel &gt; Display &gt; Settings &gt; Color Quality) and saw it was running at 16 bit.  There was no option to set it to 24-bit, so I chose the option &#8220;Highest (32 bit)&#8221;.  No more disabled resume button!</p>
<p>I think the cause of the problem was plugging my laptop into the projector at work yesterday.  It apparently changed my color depth and Windows didn&#8217;t reset it when I exited presentation mode.</p>
<p><strong>Execution of last command failed</strong></p>
<p>Trying to reconnect to my NX session kept failing.  I hit the Details button and saw the following:</p>
<pre><code>NX&gt; 596 NX&gt; 596 ERROR: NXNODE Ver. 3.4.0-6  (Error id e76DC5C)
NX&gt; 596 NX&gt; 596 ERROR: resume session: run commands
NX&gt; 596 NX&gt; 596 ERROR: execution of last command failed
NX&gt; 596 NX&gt; 596 last command: '/bin/kill -USR2 16905'
NX&gt; 596 NX&gt; 596 exit value: 1
NX&gt; 596 NX&gt; 596 stdout:
NX&gt; 596 NX&gt; 596 stderr: /bin/kill: 16905: No such process</code></pre>
<p>The only thing I found that would let me connect to my box via NX at all was to &#8220;rm /usr/NX/var/db/running/*&#8221; in order to kill my current session.  Killing the session is a sucky option, but at least now I can use NX again.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/trouble-resuming-nx-session/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Struts 2 on Google App Engine</title>
		<link>http://www.benmccann.com/dev-blog/using-struts-2-on-google-app-engine/</link>
		<comments>http://www.benmccann.com/dev-blog/using-struts-2-on-google-app-engine/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 07:50:15 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Struts 2]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=240</guid>
		<description><![CDATA[Google App Engine (GAE) has some great benefits such as scalability and the fact that it&#8217;s free to start.  When using Struts 2 with Google App Engine there a few things to keep in mind. The first is that it runs inside a security sandbox that is more restrictive than your typical Java environment.  This [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/appengine/">Google App Engine (GAE)</a> has some great benefits such as scalability and the fact that it&#8217;s free to start.  When using <a href="http://struts.apache.org/2.x/index.html">Struts 2</a> with Google App Engine there a few things to keep in mind.</p>
<p>The first is that it runs inside a security sandbox that is more restrictive than your typical Java environment.  This means that <a href="http://www.opensymphony.com/ognl/">OGNL</a>, the expression language that Struts 2 uses, will not work correctly out of the box.  You can fix this by adding a listener as described in <a href="http://programmingpanda.blogspot.com/2009/07/struts-2-ongl-issue-on-google-app.html">this article</a>.  An example listener can be found <a href="http://code.google.com/p/usaopengov/source/browse/trunk/src/org/usaopengov/action/security/OgnlFixListener.java">here</a> and is used in <a href="http://code.google.com/p/usaopengov/source/browse/trunk/war/WEB-INF/web.xml">this web.xml file</a>.</p>
<p>The second problem is that Google App Engine has some special URLs that it uses.  If you try to visit them, Struts 2 will attempt to process the request as if it&#8217;s a Struts 2 Action and will bomb out when the Action can&#8217;t be found.  You can add an exclusion filter to your struts.xml to counteract this problem:</p>
<pre><code>&lt;constant name="struts.action.excludePattern" value="/_ah/.*"/&gt;</code></pre>
<p>﻿</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/using-struts-2-on-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>openSUSE 11.2 Setup and Review</title>
		<link>http://www.benmccann.com/dev-blog/opensuse-11-2-setup-and-review/</link>
		<comments>http://www.benmccann.com/dev-blog/opensuse-11-2-setup-and-review/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 08:05:56 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[openSUSE]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=222</guid>
		<description><![CDATA[openSUSE is my favorite Linux distribution.  Linux in general has some usability frustrations as a desktop user, so I hope to share some of the ways they can be dealt with.  If you have questions of your own leave a comment. Fix horrible bug that breaks buttons GDK has a horrible debilitating bug that was [...]]]></description>
			<content:encoded><![CDATA[<p>openSUSE is my favorite Linux distribution.  Linux in general has some usability frustrations as a desktop user, so I hope to share some of the ways they can be dealt with.  If you have questions of your own leave a comment.</p>
<p><strong>Fix horrible bug that breaks buttons</strong></p>
<p>GDK has a horrible debilitating bug that was not caught before release and at the time of writing the fix has not been backported as an online update.  This makes buttons in both Flash and Eclipse unresponsive to clicking.  You need to &#8220;export GDK_NATIVE_WINDOWS=true&#8221; in order for things to work correctly.  I added this in my ~/.bashrc file:</p>
<pre><code># .bashrc

# User specific aliases and functions
alias untargz="tar zxvf"

export GDK_NATIVE_WINDOWS=true
export PATH=/usr/local/eclipse/eclipse-3.5:$PATH

# Source global definitions
if [ -f /etc/bashrc ]; then
********. /etc/bashrc
fi</code></pre>
<p><strong>1-click installers &#8211; Setup graphics card, multimedia, and fonts<br />
</strong></p>
<p>An easy way to install most of the software you need is to use a <a href="http://opensuse-community.org/1-click-collection">1-click installer</a>.  If you have an NVIDIA or ATI graphics card, then you’ll want to install the drivers using one of these installers.  I also recommend installing &#8220;Codecs pack for KDE&#8221;, &#8220;VLC Media Player&#8221;, and &#8220;Fonts with subpixel hinting enabled&#8221;.</p>
<p><strong>Install Chrome</strong></p>
<p><a href="http://www.google.com/chrome?platform=linux">Download it from Google</a>.</p>
<p><strong>Setup multimedia </strong></p>
<p>This is a perennial setup step on Linux distributions.  We’ll install the codecs needed to watch videos on Linux.</p>
<ol>
<li>YaST &gt; “Software” &gt; “Software Repositories”</li>
<li>Click “Add”</li>
<li>Select “Community Repositories”</li>
<li>Select “Packman Repository” if it is not already</li>
<li>YaST &gt; “Software” &gt; “Software Management”</li>
<li>Install libxine1-codecs.</li>
</ol>
<p><strong>Setup time synchronization</strong></p>
<p>NTP (Network Time Protocol) can be used to synch your system&#8217;s clock to a server on the internet.</p>
<ol>
<li>YaST &gt; “System” &gt; “Date and Time”</li>
<li>Click “Change&#8230;”</li>
<li>Select &#8220;Synchronize with NTP Server&#8221;</li>
<li>Add the server for your region from pool.ntp.org (e.g. I used 0.us.pool.ntp.org since I&#8217;m in the United States)</li>
<li>Check the &#8220;Save NTP Configuration&#8221;</li>
<li>If you hit &#8220;Configure&#8230;&#8221; you can also add backup servers (e.g. 1.us.pool.ntp.org , 2.us.pool.ntp.org , etc.)</li>
</ol>
<p><strong>Setup a static IP address </strong></p>
<p>This step is optional and is meant for people that know what a static IP is and want to set one up.  Having a static IP address is very nice when you want to remote desktop to your server or access it in some other way without worrying about what the IP address is.  There may also need to be some configuration done on your router for this one.  Or you may prefer to investigate DHCP reservations if your router supports them.</p>
<ol>
<li>YaST &gt; “Network Devices” &gt; “Network Settings”</li>
<li>Under Hostname/DNS, you may change your hostname and Domain Name if you prefer</li>
<li>Under Global Options, switch to &#8220;Traditional Method with ifup&#8221;</li>
<li>Under “Overview”, select your network card and click “Edit”</li>
<li>Enter your static IP (besure to also enter DNS and gateway information)</li>
<li>Hit save</li>
</ol>
<p><strong>Setup a network file share (NFS) using Samba<br />
</strong></p>
<p>Another optional step, Samba allows you to share files on your computer with others on the network.</p>
<ol>
<li>YaST &gt; “Software” &gt; “Software Management”</li>
<li>Install “samba”</li>
<li>YaST &gt; “Network Services” &gt; “Samba Server”</li>
<li>Choose &#8220;Not a domain controller&#8221;, start during boot, and tell it to unblock the firewall</li>
<li>Change sharing settings as you’d like and hit “Finish”</li>
<li>Add a user to Samba by running “smbpasswd -a username” where username is the user you’d like to create.</li>
<li>Connect from your Windows machine by right clicking &#8220;My Computer&#8221; and browsing your network.  If you have trouble connecting you might also try opening a &#8220;Run&#8230;&#8221; dialog off the start menu and typing in your IP address with two leading slashes e.g. &#8220;\\192.168.10.2&#8243;</li>
</ol>
<p><strong>Setup remote desktop through NX<br />
</strong></p>
<p>The two main remote desktop softwares for Linux are VLC and NX.  NX is much faster and is what I would recommend.  Unfortunately, I have not been able to get desktop sharing to fully work.  If you get desktop shadowing to work properly then please let me know.  In addition to installing NX, we’ll also open the corresponding port in the firewall so that we can connect from another machine.</p>
<ol>
<li>Download the <a href="http://www.nomachine.com/select-package.php?os=linux&amp;id=1">NX Linux packages</a></li>
<li>Run “rpm -iv nxclient-3.4.0-5.x86_64.rpm”, “rpm -iv nxnode-3.4.0-5.x86_64.rpm”, and “rpm -iv nxserver-3.4.0-5.x86_64.rpm”</li>
<li>Run “/usr/NX/scripts/setup/nxserver &#8211;install”</li>
<li>Run “/usr/NX/bin/nxserver &#8211;keygen”</li>
<li>In your NX client, open “Configure…” &gt; “General” tab &gt; “Key …”</li>
<li>Copy the contents of “/usr/NX/share/keys/default.id_dsa.key” into the key window and save it</li>
<li>Open “/usr/NX/etc/server.cfg”</li>
<li>Uncomment ‘EnableSessionShadowingAuthorization = &#8220;1&#8243; and change the value to &#8220;0&#8243; which will enable you to select “Shadow” in the client under the General &gt; Desktop if you’d like to do <a href="http://nomachine.org/ar/view.php?ar_id=AR11B00098">desktop sharing</a>.</li>
<li>YaST &gt; “Security and Users” &gt; “Firewall” &gt; “Allowed Services”</li>
<li>Allow “Secure Shell Server”</li>
</ol>
<p><strong>Upgrade to the ext4 file system<br />
</strong></p>
<p>ext4 is the new default file system on openSUSE 11.2.  If you did a clean install, you will be running ext4 by default.  However, if you have a drive you did not reformat when installing the OS then you may be running ext3.  For example, I have two drives: 1 60 gig drive I use as my root partition and a 500 gig drive I use as my home directory.  When I installed openSUSE 11.2, I wiped the root partition and reformatted it as ext4, but I wanted to keep the data on my home directory, so I couldn&#8217;t reformat it and left it as ext3.</p>
<ol>
<li>Run &#8220;df -T&#8221; to see your file system types.  For me it showed /dev/sdb1 as ext4 mounted on /home</li>
<li>Run init 1 to switch <a href="http://en.wikipedia.org/wiki/Runlevel#SUSE_Linux">runlevels</a></li>
<li>Unmount the drive:  e.g. &#8220;umount /home&#8221;</li>
<li>Run e2fsck on the drive : e.g. e2fsck /dev/sdb1</li>
<li>Run tune2fs: e.g. tune2fs -O extents,uninit_bg /dev/sdb1</li>
<li>Edit /etc/fstab to change ext3 to ext4 on the drive</li>
<li>Run &#8220;mount -a&#8221; to remount the drive</li>
</ol>
<p><strong>Review: The Problem with Linux is Usability and Resource Allocation<br />
</strong></p>
<p>openSUSE is as good a Linux desktop as you&#8217;ll find.  Unfortunately that&#8217;s not saying as much as I&#8217;d like.  There are so many broken things on the system and yet so much effort was put into developing things that average person doesn&#8217;t give a rat&#8217;s ass about. There&#8217;s a whole load of crap that comes with the system that&#8217;s a waste.  It&#8217;s incredibly frustrating to me to see so many resources go into this software that few people care about.  I don&#8217;t need Marble when the far superior Google Earth is available on Linux.  I don&#8217;t need Kaffeine when VLC is a better alternative.  Most of the games are a waste and can&#8217;t hold a candle to the hundreds of Flash games available online.   I&#8217;ve never used digiKam, but have to assume that at best it&#8217;s <a href="http://www.google.com/linuxrepositories/index.html">Picasa</a>&#8216;s ugly stepsister.  There are dozens of programs I&#8217;d rather use than KDE PIM: GMail, Thunderbird, LinkedIn, etc.  The list goes on, and on, and on.  Why are we building this stuff?  The single biggest improvement in openSUSE 11.2 is that Firefox is now the default browser.  This took way too long, but is a welcomed change.  I wish VLC would replace Kaffeine.  Someone at Novell, Canonical, et. al. needs to do some user testing.  Any 12-year-old kid would tell you you&#8217;re crazy if you think people would rather use Marble than Google Earth.  Linux distros have done an absolutely horrifyingly awful job of picking the best software to be the default.  Instead of wasting all this time, how about we come together and decide to make an operating system that just works?  There are so many usability frustrations that I&#8217;d like to see solved instead.  Novell, Canonical, and the other leaders in this area need to step up.</p>
<p>As mentioned, there are a lot of usability problems.  For example, Flash was unusable in full screen mode after install.  It turned out this was because I hadn&#8217;t yet installed my NVIDIA driver.  But this is a big problem.  How would any casual user know they had to do this?  My parents, brother, or sister would not have known to do this despite being reasonably computer savvy.  I knew because I&#8217;ve used Linux for many years, but if it requires a computer science degree to watch a YouTube video then you&#8217;ve failed.  And when I did realize I needed to install the driver, I needed to know which of three drivers I wanted.  Are you serious?  I could just imagine asking my mom what graphics card she has.  That would be a fun conversation.  It&#8217;s 2009.  And you don&#8217;t have the ability to detect my hardware?  I understand that there are licensing issues, but once I&#8217;ve said I want to install a graphics driver you should be able to tell me which one I need.  I want to get rid of the &#8220;Recently Used&#8221; option on the Kicker menu like I can with classic, but there&#8217;s no option to.  I don&#8217;t understand why YaST has a &#8220;Media Check&#8221; option.  Can&#8217;t you tell there&#8217;s no CD/DVD in my drive?  I tried to edit my network settings with YaST and it told me to use NetworkManager or change the setup method to Traditional with ifup.  How do I do either of those things?  I don&#8217;t know what NetworkManager is or how to open it.  There&#8217;s nothing in any of the menus called NetworkManager.  When I started Firefox it asked me if I wanted to use Flash, gnash, or swfdec.  But I tried gnash and swfdec and neither could play a Hulu video, so are you insane?  Of course I don&#8217;t want to use either of those.  Why are you confusing me?  Flash on Linux is a big problem.  The controls on the Hulu just stop working with frustrating frequency.  I can&#8217;t figure out why Amarok and Kaffeine are both broken.  I could go on, but you get my point.  Let&#8217;s fix these problems instead of building more crap no one asked for.  I know how much of this work has been done by volunteers and am extremely grateful for it.  I&#8217;ve contributed to several open source projects myself and know what it&#8217;s like, so I hope those reading know I am thankful to have this amazing free software.  I&#8217;m happy for what&#8217;s been done and am hoping the leaders of KDE and openSUSE will make some hard choices about what&#8217;s worth investing in and supporting, so that these projects can become successful in the mainstream world because as it stands now, even as great as it is, Linux simply isn&#8217;t ready.</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 8px; width: 1px; height: 1px;">
<p><strong>Install NVIDIA drivers<br />
</strong></p>
<p>If you have an NVIDIA card, then you’ll want to install the drivers.  Use the <a href="http://en.opensuse.org/NVIDIA">NVIDIA driver 1-click installer</a>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/opensuse-11-2-setup-and-review/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Case Study: Usable and Unusable APIs</title>
		<link>http://www.benmccann.com/dev-blog/case-study-good-and-bad-apis/</link>
		<comments>http://www.benmccann.com/dev-blog/case-study-good-and-bad-apis/#comments</comments>
		<pubDate>Sun, 26 Jul 2009 00:13:50 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=210</guid>
		<description><![CDATA[It was the best of times, it was the worst of times&#8230; It was the age of wisdom, it was the season of light.  A great library called dom4j was written with its users in mind.  It included a quick start guide and a cookbook for people that actually wanted to get things done.  Converting [...]]]></description>
			<content:encoded><![CDATA[<p>It was the best of times, it was the worst of times&#8230;</p>
<p>It was the age of wisdom, it was the season of light.  A great library called <a href="http://www.dom4j.org/dom4j-1.6.1/guide.html">dom4j</a> was written with its users in mind.  It included a <a href="http://www.dom4j.org/dom4j-1.6.1/guide.html">quick start guide</a> and a <a href="http://www.dom4j.org/dom4j-1.6.1/cookbook.html">cookbook</a> for people that actually wanted to get things done.  Converting a document to a String took 15 characters: document.asXML().  But there were too many competing XML parsing implementations, so a <a href="http://java.sun.com/j2se/1.5.0/docs/api/org/w3c/dom/Document.html">standard</a> was created.  And sadly, dom4j has not been updated to adhere to that standard.</p>
<p>It was the age of foolishness, it was the epoch of incredulity.  15 characters to turn a document into a string?  That is far too few.  What will we tell our managers when they ask how many lines of code we have written?  We have a better way and it is called <a href="http://xerces.apache.org/xerces-j/">Xerces</a>:<br />
<code>
<pre>import java.io.StringWriter;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Node;

public final class XmlUtil {

  private static final TransformerFactory factory = TransformerFactory.newInstance();

  public static String toString(Node node) {
    if (node == null) {
      return null;
    }
    try {
      Source source = new DOMSource(node);
      StringWriter stringWriter = new StringWriter();
      Result result = new StreamResult(stringWriter);
      Transformer transformer = factory.newTransformer();
      transformer.transform(source, result);
      return stringWriter.getBuffer().toString();
    } catch (TransformerConfigurationException e) {
      e.printStackTrace();
    } catch (TransformerException e) {
      e.printStackTrace();
    }
    return null;
  }

}</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/case-study-good-and-bad-apis/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Sample log4j.properties file</title>
		<link>http://www.benmccann.com/dev-blog/sample-log4j-properties-file/</link>
		<comments>http://www.benmccann.com/dev-blog/sample-log4j-properties-file/#comments</comments>
		<pubDate>Sat, 18 Jul 2009 21:45:14 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[log4j]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=206</guid>
		<description><![CDATA[I always find the hardest part of getting started with log4j is creating a log4j.properties file. For that reason, I&#8217;ve posted an example below. This file configures log4j to log any messages of level info or higher to the console except for classes under the com.dappit.Dapper.parser or org.w3c.tidy packages. #------------------------------------------------------------------------------ # # The following properties [...]]]></description>
			<content:encoded><![CDATA[<p>I always find the hardest part of getting started with log4j is creating a log4j.properties file.  For that reason, I&#8217;ve posted an example below. This file configures log4j to log any messages of level info or higher to the console except for classes under the com.dappit.Dapper.parser or org.w3c.tidy packages.</p>
<pre><code>#------------------------------------------------------------------------------
#
#  The following properties set the logging levels and log appender.  The
#  log4j.rootCategory variable defines the default log level and one or more
#  appenders.  For the console, use 'S'.  For the daily rolling file, use 'R'.
#  For an HTML formatted log, use 'H'.
#
#  To override the default (rootCategory) log level, define a property of the
#  form (see below for available values):
#
#        log4j.logger. =
#
#    Available logger names:
#      TODO
#
#    Possible Log Levels:
#      FATAL, ERROR, WARN, INFO, DEBUG
#
#------------------------------------------------------------------------------
log4j.rootCategory=INFO, S

log4j.logger.com.dappit.Dapper.parser=ERROR
log4j.logger.org.w3c.tidy=FATAL

#------------------------------------------------------------------------------
#
#  The following properties configure the console (stdout) appender.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.S = org.apache.log4j.ConsoleAppender
log4j.appender.S.layout = org.apache.log4j.PatternLayout
log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n

#------------------------------------------------------------------------------
#
#  The following properties configure the Daily Rolling File appender.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.R = org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File = logs/bensApps.log
log4j.appender.R.Append = true
log4j.appender.R.DatePattern = '.'yyy-MM-dd
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n

#------------------------------------------------------------------------------
#
#  The following properties configure the Rolling File appender in HTML.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.H = org.apache.log4j.RollingFileAppender
log4j.appender.H.File = logs/bensApps.html
log4j.appender.H.MaxFileSize = 100KB
log4j.appender.H.Append = false
log4j.appender.H.layout = org.apache.log4j.HTMLLayout</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/sample-log4j-properties-file/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
