<?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>java rants &#187; Java</title>
	<atom:link href="http://www.javarants.com/category/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.javarants.com</link>
	<description>Rants about Java and other internet technologies by Sam Pullara</description>
	<lastBuildDate>Thu, 11 Mar 2010 23:26:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Using JAX-RS with Protocol Buffers for high-performance REST APIs</title>
		<link>http://www.javarants.com/2008/12/27/using-jax-rs-with-protocol-buffers-for-high-performance-rest-apis/</link>
		<comments>http://www.javarants.com/2008/12/27/using-jax-rs-with-protocol-buffers-for-high-performance-rest-apis/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 03:55:59 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.javarants.com/?p=955</guid>
		<description><![CDATA[One of the great things about the JAX-RS specification is that it is very extensible and adding new providers for different mime-types is very easy.  One of the interesting binary protocols out there is Google Protocol Buffers.  They are designed for high-performance systems and drastically reduce the amount of over-the-wire data and also [...]]]></description>
			<content:encoded><![CDATA[<p>One of the great things about the <a href="http://jcp.org/aboutJava/communityprocess/final/jsr311/index.html">JAX-RS specification</a> is that it is very extensible and adding new providers for different mime-types is very easy.  One of the interesting binary protocols out there is <a href="http://code.google.com/apis/protocolbuffers/docs/overview.html">Google Protocol Buffers</a>.  They are designed for high-performance systems and drastically reduce the amount of over-the-wire data and also the amount of CPU spent serializing and deserializing that data.  There are other similar frameworks out there including <a href="http://java.sun.com/developer/technicalArticles/xml/fastinfoset/">Fast Infoset</a> and <a href="http://incubator.apache.org/thrift/">Thrift</a>.  Extending JAX-RS to support those protocols is nearly identical so all of the ideas I&#8217;ll talk about are generally valid for those frameworks as well.  The one limitation that we will table for now is that JAX-RS only works over HTTP and will not work for raw socket protocols and the high-performance aspect of protobufs is somewhat reduced by our dependency on the HTTP envelope.  My assumption is that you have done your homework and know that message passing is your overriding bottleneck.<br />
<span id="more-955"></span><br />
The first thing you will need to do to get started is to download and build Protocol Buffers.  You can get the latest stable release from <a href="http://code.google.com/p/protobuf/">here</a>.  All the example code you will find in this blog post was developed against protobuf-2.0.3 and the JAX-RS 1.0 specification (using <a href="https://jersey.dev.java.net/">jersey-1.0.1</a>) though I don&#8217;t expect the API to change very much going forward. Once you have <em>protoc</em> in your path you are ready to create your first JAX-RS / protobuf project.</p>
<p>The dependencies you will need to create the application are actually quite small. I use <a href="http://maven.apache.org/">Maven</a> (and <a href="http://www.jetbrains.com/idea/download/">IntelliJ 8.0</a>) to do my development so that is how I&#8217;ll describe what you need.  For running the application you&#8217;ll need these installed:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">com.sun.jersey</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">jersey-server</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">1.0.1</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">com.sun.grizzly</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">grizzly-servlet-webserver</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">1.8.6.3</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">com.google.protobuf</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">protobuf-java</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">2.0.3</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
</span>
</pre>
<p>Then to execute the tests that we will create to verify that things are working as expected you&#8217;ll need two additional test-time only dependencies:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">com.sun.jersey</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">jersey-client</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">1.0.1</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">scope</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">test</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">scope</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">junit</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">junit</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">4.5</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">scope</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">test</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">scope</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
</span>
</pre>
<p>Not a huge set of dependencies on the surface but Maven does hide a lot of the complexity underneath &#8212; total is about 15 jars (mostly grizzly).  The next step is to create a Protocol Buffer using their definition language.  Instead of making one up myself, I&#8217;ll just use the one from their <a href="http://code.google.com/apis/protocolbuffers/docs/javatutorial.html">example</a>, addressbook.proto:</p>
<pre>
<span style="color: rgb(102,0,0); font-weight: bold; font-style: normal; ">package</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> tutorial;

</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">option</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,102,102); font-weight: bold; font-style: normal; ">java_package</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> = </span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;com.sampullara.jaxrsprotobuf.tutorial&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">option</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,102,102); font-weight: bold; font-style: normal; ">java_outer_classname</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> = </span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;AddressBookProtos&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;

</span><span style="color: rgb(102,0,0); font-weight: bold; font-style: normal; ">message</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Person {
  </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">required</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">string</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> name = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">1</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
  </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">required</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">int32</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> id = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">2</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
  </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">optional</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">string</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> email = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">3</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;

  </span><span style="color: rgb(102,0,0); font-weight: bold; font-style: normal; ">enum</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> PhoneType {
    MOBILE = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">0</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
    HOME = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">1</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
    WORK = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">2</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
  }

  </span><span style="color: rgb(102,0,0); font-weight: bold; font-style: normal; ">message</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> PhoneNumber {
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">required</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">string</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> number = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">1</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">optional</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> PhoneType type = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">2</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> [</span><span style="color: rgb(0,102,102); font-weight: bold; font-style: normal; ">default</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> = HOME];
  }

  </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">repeated</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> PhoneNumber phone = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">4</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
}

</span><span style="color: rgb(102,0,0); font-weight: bold; font-style: normal; ">message</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> AddressBook {
  </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">repeated</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Person person = </span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">1</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
}
</span>
</pre>
<p>A fairly simple data description but it does touch on a lot of the features of Protocol Buffers including embedded messages, enums, repeating entries and their type system.  Now lets define a simple service that we want to get to work using the <a href="https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/ext/package-summary.html">extension SPI</a> of JAX-RS.  This service will have two methods, a GET method for returning a new instance of a <em>Person</em> and a POST method that just reflects what is passed to it back to the caller unmodified.  That will also let us do some round trip testing.  Here is the proposed service:</p>
<pre>
<span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">package</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> com.sampullara.jaxrsprotobuf.tutorial;

</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">import</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> javax.ws.rs.*;

</span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Path</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;/person&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> AddressBookService {
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@GET</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Produces</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/x-protobuf&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> AddressBookProtos.Person getPerson() {
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> AddressBookProtos.Person.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">newBuilder</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">()
                .setId(</span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">1</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
                .setName(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Sam&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
                .setEmail(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;sam@sampullara.com&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
                .addPhone(AddressBookProtos.Person.PhoneNumber.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">newBuilder</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">()
                        .setNumber(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;415-555-1212&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
                        .setType(AddressBookProtos.Person.PhoneType.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">MOBILE</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
                        .build())
                .build();
    }

    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@POST</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Consumes</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/x-protobuf&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Produces</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/x-protobuf&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> AddressBookProtos.Person reflect(AddressBookProtos.Person person) {
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> person;
    }
}
</span>
</pre>
<p>For each of these methods we&#8217;ve restricted them to either consuming or producing content of type <em>application/x-protobuf</em>.  When JAX-RS sees a request that matches that type or a caller that accepts that type these will be valid endpoints to satisfy those requests.  Out of the box, Jersey includes readers and writers for a variety of types including form data, XML and JSON.  They also provide a way to register new mime-type readers and writers with a very simple set of annotations on classes that implement either MessageBodyReader or MessageBodyWriter.  The class that implements reading is very straight forward, first it calls you back to see if you can read something, then it calls you to actually read it passing you the stream of data.  Here is the implementation:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Provider</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Consumes</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/x-protobuf&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">static</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> ProtobufMessageBodyReader </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">implements</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> MessageBodyReader&lt;Message&gt; {
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">boolean</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> isReadable(Class&lt;?&gt; type, Type genericType, Annotation[] annotations, MediaType mediaType) {
            </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Message.</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.isAssignableFrom(type);
        }

        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Message readFrom(Class&lt;Message&gt; type, Type genericType, Annotation[] annotations,</span>
<span style="color: rgb(0,0,128); font-weight: normal; font-style: normal; ">                    MediaType mediaType, MultivaluedMap&lt;String, String&gt; httpHeaders, </span>
<span style="color: rgb(0,0,128); font-weight: normal; font-style: normal; ">                    InputStream entityStream) </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">throws</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> IOException, WebApplicationException {
            </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">try</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> {
                Method newBuilder = type.getMethod(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;newBuilder&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
                GeneratedMessage.Builder builder = (GeneratedMessage.Builder) newBuilder.invoke(type);
                </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> builder.mergeFrom(entityStream).build();
            } </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">catch</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> (Exception e) {
                </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">throw</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">new</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> WebApplicationException(e);
            }
        }
    }
</span>
</pre>
<p>This class either needs to be under a package that is registered to be scanned when the application starts or it could be explicitly registered by extending <em>Application</em>.  You&#8217;ll see in our Main method later we use the former strategy.  You&#8217;ll note that in order for us to instantiate a new Protocol Buffer builder we need to use reflection on the type that JAX-RS is expecting. I&#8217;ve convinced myself thats the best way to do it but please comment if you can think of a better way.  If there were additional configuration information you needed to pass to the reader you could annotate the methods with that information and receive it here in the annotations array.</p>
<p>The writer is a bit more complicated because in addition to the <em>isWritable</em> and <em>writeTo</em> methods you have to be able to return the size that you are going to write.  I was hoping that Protocol Buffers supported a quick way to sum the size of an object but alas they do not so instead I actually do the write in <em>getSize</em> and temporarily store the result with a weak map.  In the future I&#8217;d like to see streaming better supported.  Here is how I implemented the writer:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Provider</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Produces</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/x-protobuf&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">static</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> ProtobufMessageBodyWriter </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">implements</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> MessageBodyWriter&lt;Message&gt; {
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">boolean</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> isWriteable(Class&lt;?&gt; type, Type genericType, Annotation[] annotations, MediaType mediaType) {
            </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Message.</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.isAssignableFrom(type);
        }

        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">private</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Map&lt;Object, </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">byte</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">[]&gt; </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">buffer</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> = </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">new</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> WeakHashMap&lt;Object, </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">byte</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">[]&gt;();

        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">long</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> getSize(Message m, Class&lt;?&gt; type, Type genericType, Annotation[] annotations, MediaType mediaType) {
            ByteArrayOutputStream baos = </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">new</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> ByteArrayOutputStream();
            </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">try</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> {
                m.writeTo(baos);
            } </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">catch</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> (IOException e) {
                </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> -</span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">1</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
            }
            </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">byte</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">[] bytes = baos.toByteArray();
            </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">buffer</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.put(m, bytes);
            </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> bytes.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">length</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
        }

        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">void</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> writeTo(Message m, Class type, Type genericType, Annotation[] annotations, </span>
<span style="color: rgb(0,0,128); font-weight: normal; font-style: normal; ">                    MediaType mediaType, MultivaluedMap httpHeaders,</span>
<span style="color: rgb(0,0,128); font-weight: normal; font-style: normal; ">                    OutputStream entityStream) </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">throws</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> IOException, WebApplicationException {
            entityStream.write(</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">buffer</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.remove(m));
        }
    }
</span>
</pre>
<p>I&#8217;d love to get around the non-streaming limitation in this integration so if you have any ideas, send them my way.  Now we also need to generate the code from the Protocol Buffer definition file.  I again use Maven to do that with this additional stanza:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">plugin</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
        </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">maven-antrun-plugin</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
        </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">executions</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
          </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">execution</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
            </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">id</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">generate-sources</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">id</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
            </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">phase</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">generate-sources</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">phase</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
            </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">configuration</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
              </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">tasks</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
                </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">mkdir</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,255); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dir=</span><span style="color: rgb(0,128,0); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">&apos;target/generated-sources&apos;</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; "> /&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
                </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">exec</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,255); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">executable=</span><span style="color: rgb(0,128,0); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">&apos;protoc&apos;</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
                  </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">arg</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,255); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">value=</span><span style="color: rgb(0,128,0); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">&apos;--java_out=target/generated-sources&apos;</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; "> /&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
                  </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">arg</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,255); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">value=</span><span style="color: rgb(0,128,0); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">&apos;src/main/resources/addressbook.proto&apos;</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; "> /&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
                </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">exec</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
              </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">tasks</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
              </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">sourceRoot</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">target/generated-sources</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">sourceRoot</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
            </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">configuration</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
            </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">goals</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
              </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">goal</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">run</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">goal</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
            </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">goals</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
          </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">execution</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
        </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">executions</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">plugin</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
</span>
</pre>
<p>That should now be enough to build the service itself along with the message readers and writers.  The last thing to do on the production side is to show how you would deploy this using the <a href="https://grizzly.dev.java.net/">Grizzly</a> container:</p>
<pre>
<span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Main {
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">static</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">final</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> URI </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">BASE_URI</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> = UriBuilder.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">fromUri</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;http://localhost/&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">).port(</span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">9998</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">).build();

    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">static</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">void</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> main(String[] args) </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">throws</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> IOException {
        System.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">out</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.println(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Starting grizzly...&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
        URI uri = </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">BASE_URI</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
        SelectorThread threadSelector = </span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">createServer</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(uri);
        System.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">out</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.println(String.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">format</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Try out %sperson</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">n</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">Hit enter to stop it...&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, uri));
        System.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">in</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.</span><span style="color: rgb(0,0,0); background-color: rgb(246,235,188); font-weight: normal; font-style: normal; ">read</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">();
        threadSelector.stopEndpoint();
    }

    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">static</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> SelectorThread createServer(URI uri) </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">throws</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> IOException {
        Map&lt;String, String&gt; initParams = </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">new</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> HashMap&lt;String, String&gt;();
        initParams.put(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;com.sun.jersey.config.property.packages&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, </span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;com.sampullara&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> GrizzlyWebContainerFactory.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">create</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(uri, initParams);
    }
}
</span>
</pre>
<p>Jersey+Grizzly makes it very easy instantiate a new servlet container at a particular URI and immediately access the REST services that you have deployed.  For testing, it is nice to be able to bring up an actual environment so easily.  In our tests we are also going to make use of the REST client that is included with Jersey so that you can see the serialization on both sides of the wire.  In order to get the server up and running during the test we need to implement <em>setUp</em>() and <em>tearDown</em>():</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">private</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> SelectorThread </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">threadSelector</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">private</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> WebResource </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">r</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;

    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Override</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">protected</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">void</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> setUp() </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">throws</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Exception {
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">super</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.setUp();

        </span><span style="color: rgb(128,128,128); font-weight: normal; font-style: italic; ">//start the Grizzly web container and create the client</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
        </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">threadSelector</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> = Main.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">createServer</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(Main.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">BASE_URI</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);

        ClientConfig cc = </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">new</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> DefaultClientConfig();
        cc.getClasses().add(ProtobufProviders.ProtobufMessageBodyReader.</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
        cc.getClasses().add(ProtobufProviders.ProtobufMessageBodyWriter.</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
        Client c = Client.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">create</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(cc);
        </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">r</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> = c.resource(Main.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">BASE_URI</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
    }

    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Override</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">protected</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">void</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> tearDown() </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">throws</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Exception {
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">super</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.tearDown();
        </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">threadSelector</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.stopEndpoint();
    }

</span>
</pre>
<p>The client doesn&#8217;t have the special class scanning capability so we directly register our providers with the client and point it at the same URI that the server is running on.  Being able to control those in your tests makes integration tests far easier as you don&#8217;t have to worry about mismatched configurations.  The first tests we will run will be using the Jersey client:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">void</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> testUsingJerseyClient() {
        WebResource wr = </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">r</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.path(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;person&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
        AddressBookProtos.Person p = wr.get(AddressBookProtos.Person.</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
        </span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">assertEquals</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Sam&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, p.getName());

        AddressBookProtos.Person p2 = wr.type(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/x-protobuf&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">).post(AddressBookProtos.Person.</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, p);
        </span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">assertEquals</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(p, p2);
    }
</span>
</pre>
<p>Notice how you can build up a web resource incrementally adding additional constraints or paths to it until ultimately you call one of the HTTP methods on that resource.  We also see that using that client API we get typed access to the REST server.  Slightly more complicated is another test using direct HTTP connections:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">void</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> testUsingURLConnection() </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">throws</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> IOException {
        AddressBookProtos.Person person;
        {
            URL url = </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">new</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> URL(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;http://localhost:9998/person&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
            URLConnection urlc = url.openConnection();
            urlc.setDoInput(</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">true</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
            urlc.setRequestProperty(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Accept&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, </span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/x-protobuf&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
            person = AddressBookProtos.Person.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">newBuilder</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">().mergeFrom(urlc.getInputStream()).build();
            </span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">assertEquals</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Sam&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, person.getName());
        }
        {
            URL url = </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">new</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> URL(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;http://localhost:9998/person&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setDoInput(</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">true</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
            urlc.setDoOutput(</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">true</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
            urlc.setRequestMethod(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;POST&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
            urlc.setRequestProperty(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Accept&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, </span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/x-protobuf&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
            urlc.setRequestProperty(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Content-Type&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, </span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/x-protobuf&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
            person.writeTo(urlc.getOutputStream());
            AddressBookProtos.Person person2 = AddressBookProtos.Person.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">newBuilder</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">().mergeFrom(urlc.getInputStream()).build();
            </span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">assertEquals</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(person, person2);
        }
    }
</span>
</pre>
<p>This code looks more like what a non-Java client might do to access your REST service and deserialize the information using their Protocol Buffers.  In fact, why don&#8217;t we try this with some Python 2.5 code:</p>
<pre>
<span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">import</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">urllib</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">import</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> addressbook_pb2

f = </span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">urllib</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.urlopen(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;http://localhost:9998/person&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
person = addressbook_pb2.Person()
</span><span style="color: rgb(0,0,0); background-color: rgb(246,235,188); font-weight: normal; font-style: normal; ">person.ParseFromString</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(f.read())
</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">print</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,0); background-color: rgb(246,235,188); font-weight: normal; font-style: normal; ">person.name</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
</span>
</pre>
<p>Works great and outputs &#8220;Sam&#8221; as expected.  Very fast but still interoperable between multiple languages in a type-safe way.  Once Thrift is further along I will likely make the same sort of interoperability possible.</p>
<p>For those that just want to open up the final product and see how it all works, here is a <a href="http://buildandtest.com/files/jaxrs-protobuf.zip">link to download it</a>.  You&#8217;ll also note that I actually use <a href="http://code.google.com/p/graven/">graven</a> under the covers to do my builds as Maven&#8217;s XML is a little too verbose for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2008/12/27/using-jax-rs-with-protocol-buffers-for-high-performance-rest-apis/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Using JAX-RS (Jersey) to build a JPA/JAXB-backed JSON REST API</title>
		<link>http://www.javarants.com/2008/12/25/using-jax-rs-jersey-to-build-a-jpajaxb-backed-json-rest-api/</link>
		<comments>http://www.javarants.com/2008/12/25/using-jax-rs-jersey-to-build-a-jpajaxb-backed-json-rest-api/#comments</comments>
		<pubDate>Fri, 26 Dec 2008 01:38:46 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[jax-rs]]></category>
		<category><![CDATA[jersey]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[jsr-311]]></category>
		<category><![CDATA[openjpa]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[toplink]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.javarants.com/?p=926</guid>
		<description><![CDATA[I've been looking for a while though to find that perfect combination of frameworks and libraries that would give me the expressive power that I want for building web applications -- now I think I've found it.]]></description>
			<content:encoded><![CDATA[<p>Building applications for deployment to the web has evolved over the last several years to be focused on dynamic behavior, separation of model/view/controller, and simplified but scalable configuration and deployment.  From a performance, tools and library perspective I&#8217;m still highly biased to development in Java over more up-and-coming languages.  However, much has been learned in the Java community from the better frameworks like Rails and those lessons should not be ignored.</p>
<p>I&#8217;ve been looking for a while though to find that perfect combination of frameworks and libraries that would give me the expressive power that I want for building web applications.  There have been many contenders from <a href="http://wiki.jruby.org/wiki/JRuby_on_Rails">JRuby on Rails</a>, to <a href="http://grails.org/">Grails</a>, to <a href="http://seamframework.org/">Seam</a> and even just writing everything myself.  Ultimately, I believe in the <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a> principle (like Rails), though I don&#8217;t think many frameworks go far enough when dealing with the database.  When you are building a web application it is rare that you are going to change what database you are using.  In fact, the majority of your scaling architecture is likely highly dependent on how you store your data.  This is why I prefer an application framework that allows me to start with the database and construct my application&#8217;s data object model from it.<br />
<span id="more-926"></span><br />
So what are my acceptance criteria for this über-framework?</p>
<ul>
<li>Great object-relational mapping tool that works well with MySQL + PostgreSQL</li>
<li>Excellent support for consuming and producing XML and JSON that integrates with the well with the data objects that the ORM tool uses</li>
<li>Supports writing MVC applications naturally</li>
<li>Support for building REST APIs with arbitrary URL mapping to service parameters</li>
<li>High straight-line performance with the ability to scale up servers</li>
<li>Great defaults that make configuration mostly unnecessary with simple deployment</li>
<li><a href="http://www.jetbrains.com/idea/">State-of-the-art IDE support</a>. I don&#8217;t like to type anymore nor memorize APIs.</li>
<li>Suitable for quick prototyping and production applications</li>
<li>Support for templating views of any output type (HTML, XML, etc)</li>
<li>Easy to unit and integration test</li>
<li>Open source</li>
</ul>
<p>Certainly a high barrier but I think I have finally found one that is a very strong contender. Amazingly, it is even coming out of the JSR standards process with a nice layer of open source on top of it.  <a href="http://jcp.org/en/jsr/detail?id=311">JSR-311</a> was stated to develop an API for providing support for <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">RESTful</a> Web Services in the Java Platform.  Not only does it do that nicely but it also has the right hooks for simple dependency injection, orthogonal to <a href="http://www.jcp.org/en/jsr/detail?id=220">JPA</a> (my favorite ORM), support for both XML and JSON natively, and except in unusual circumstances very DRY.</p>
<p>Because it is in Java and works well with JPA it satisfies a large number of my requirements before we even look at what it offers.  Another aspect of it that didn&#8217;t make the above list is that the production quality reference implementation is available as a couple of dependencies in Maven making it very easy to work with.  It also works well deployed within lightweight containers like <a href="https://grizzly.dev.java.net/">Grizzly</a>, heavier ones like <a href="http://tomcat.apache.org/">Tomcat</a> and <a href="https://glassfish.dev.java.net/">Glassfish</a>, and the REST APIs it creates can even be directly tested without any container at all. There are some things that Jersey supports that are non-standard that I think are excellent additions to the framework and should likely make it into future versions including support for templating (like JSP and Freemarker) that help it satisfy my requirements.</p>
<p>To give you an example of how terse the API can be, here is the simplest example that includes deployment as an operating web service:</p>
<pre>
<span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> Main {
    </span><span style="color: rgb(128,128,0); background-color: rgb(246,235,188); font-weight: normal; font-style: normal; ">@Path</span><span style="color: rgb(0,0,0); background-color: rgb(246,235,188); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); background-color: rgb(246,235,188); font-weight: bold; font-style: normal; ">&quot;/helloworld&quot;</span><span style="color: rgb(0,0,0); background-color: rgb(246,235,188); font-weight: normal; font-style: normal; ">)</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">static</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> HelloWorldResource {
        </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@GET</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
        </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Produces</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;text/plain&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> String getClichedMessage() {
            </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Hello World&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">;
        }
    }

    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">static</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">void</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> main(String[] args) </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">throws</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> IOException {
        Map&lt;String, String&gt; initParams = </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">new</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> HashMap&lt;String, String&gt;();
        initParams.put(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;com.sun.jersey.config.property.packages&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, </span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;com.sun.jersey.samples.helloworld&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);

        System.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">out</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.println(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Starting grizzly...&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
        URI uri = UriBuilder.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">fromUri</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;http://localhost/&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">).port(</span><span style="color: rgb(0,0,255); font-weight: normal; font-style: normal; ">9998</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">).build();
        SelectorThread threadSelector = GrizzlyWebContainerFactory.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">create</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(uri, initParams);
        System.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">out</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.println(String.</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: italic; ">format</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;Try out %shelloworld</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">\n</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">Hit enter to stop it...&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, uri));
        System.</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: italic; ">in</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.</span><span style="color: rgb(0,0,0); background-color: rgb(246,235,188); font-weight: normal; font-style: normal; ">read</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">();
        threadSelector.stopEndpoint();
    }
}
</span>
</pre>
<p>The @Path annotation lets you use URI path templates to specify the matching paths and path parameters to your REST service.  You can produce any set of content-types and content negotiation will be done for you based on the incoming request.  Exceptions can be mapped directly to error responses.  Query, Matrix, Path, Header and Cookie parameters are all supported and automatically injected based on annotations.  Here is a more sophisticated example from an application I am writing:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@GET</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Produces</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/json&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Path</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;/network/{id: [0-9]+}/{nid}&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> User getUserByNetworkId(</span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@PathParam</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;id&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">) </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">int</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> id, </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@PathParam</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;nid&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">) String networkId) {
        Query q = </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">em</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.createQuery(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;</span><span style="color: rgb(0,0,128); background-color: rgb(255,255,255); font-weight: bold; font-style: normal; ">SELECT</span><span style="color: rgb(0,128,0); background-color: rgb(237,252,237); font-weight: bold; font-style: normal; "> u </span><span style="color: rgb(0,0,128); background-color: rgb(255,255,255); font-weight: bold; font-style: normal; ">FROM</span><span style="color: rgb(0,128,0); background-color: rgb(237,252,237); font-weight: bold; font-style: normal; "> User u </span><span style="color: rgb(0,0,128); background-color: rgb(255,255,255); font-weight: bold; font-style: normal; ">WHERE</span><span style="color: rgb(0,128,0); background-color: rgb(237,252,237); font-weight: bold; font-style: normal; "> u.networkId = :id </span><span style="color: rgb(0,0,128); background-color: rgb(255,255,255); font-weight: bold; font-style: normal; ">AND</span><span style="color: rgb(0,128,0); background-color: rgb(237,252,237); font-weight: bold; font-style: normal; "> u.networkUserId = :nid</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">);
        q.setParameter(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;id&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, id);
        q.setParameter(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;nid&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, networkId);
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> (User) q.getSingleResult();
    }</span>
</pre>
<p>In this example we are implementing a GET request with two path parameters, id and uid.  They are automatically passed into the method on execution and then I use them in a JPA statement.  EntityNotFoundException is actually mapped to a 404 but I don&#8217;t need to deal with that in the method itself.  PUTs and POSTs are similarly straight-forward.  This method creates a new user:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@PUT</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Consumes</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/json&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Produces</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;application/json&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(128,128,0); font-weight: normal; font-style: normal; ">@Path</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">(</span><span style="color: rgb(0,128,0); font-weight: bold; font-style: normal; ">&quot;/create&quot;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">)
    </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">public</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> User createUser(User user) {
        user.setNetwork(</span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">em</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.getReference(Network.</span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">class</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">, user.getNetworkId()));
        </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">em</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.persist(user);
        </span><span style="color: rgb(102,14,122); font-weight: bold; font-style: normal; ">em</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">.refresh(user);
        </span><span style="color: rgb(0,0,128); font-weight: bold; font-style: normal; ">return</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> user;
    }</span>
</pre>
<p>All very declarative and readable. And works great with JPA objects that also happen to be JAXB objects.  Notice that in those examples I am returning JSON but I don&#8217;t need to explicitly convert my objects.  All that is handled by built in message readers and writers (which can be extended if need be).  </p>
<p>One thing that I will note is that after struggling with both <a href="http://openjpa.apache.org/">OpenJPA</a> (less than ideal support for the standard) and <a href="http://hibernate.org">Hibernate</a> (some very odd runtime class munging) I settled with <a href="http://oss.oracle.com/toplink-essentials-jpa.html">Toplink-Essentials</a> (the open-source version of Oracle Toplink).  It is much more robust than OpenJPA and is much cleaner at runtime than Hibernate.  Finally here is what a typical Maven dependencies look like for creating a Jersey-based web application:</p>
<pre>
<span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">  </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">repositories</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">repository</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">id</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">maven2-repository.dev.java.net</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">id</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">name</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">Java.net</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">Repository</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">for</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; "> </span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">Maven</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">name</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">url</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">http://download.java.net/maven/2</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">url</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">repository</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">repository</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">id</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">java.net</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">id</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">url</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">http://download.java.net/maven/1</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">url</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">layout</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">legacy</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">layout</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">repository</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
  </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">repositories</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
  </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependencies</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">com.sun.jersey</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">jersey-server</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">1.0.1</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">com.sun.jersey</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">jersey-json</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">1.0.1</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">com.sun.jersey</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">jersey-atom</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">1.0.1</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">mysql</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">mysql-connector-java</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">5.1.6</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">toplink.essentials</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">groupId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">toplink-essentials</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">artifactId</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
      </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: bold; font-style: normal; ">2.1-60</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">version</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
    </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependency</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
  </span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&lt;/</span><span style="color: rgb(0,0,128); background-color: rgb(239,239,239); font-weight: bold; font-style: normal; ">dependencies</span><span style="color: rgb(0,0,0); background-color: rgb(239,239,239); font-weight: normal; font-style: normal; ">&gt;</span><span style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
</span>
</pre>
<p>I was very impressed with how little it took to get going, especially with <a href="http://www.jetbrains.com/idea/download/">IntelliJ 8.0</a>&#8217;s awesome support for reading pom.xml files.  So now I&#8217;m a few days into building the application I set out to build and things are going great.  I haven&#8217;t hit any roadblocks so far and I&#8217;ve planned pretty far out already so I don&#8217;t expect to.  Though, with Jersey&#8217;s extensibility API, I think that if I do run into anything I have a great escape valve for augmenting the framework.  I&#8217;m not associated with Jersey or the JSR-311 specification but I might have to join in the fun.  This framework looks like it will have long legs in the Java community.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2008/12/25/using-jax-rs-jersey-to-build-a-jpajaxb-backed-json-rest-api/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Better Javadoc results using SearchMonkey</title>
		<link>http://www.javarants.com/2008/05/19/better-javadoc-results-using-searchmonkey/</link>
		<comments>http://www.javarants.com/2008/05/19/better-javadoc-results-using-searchmonkey/#comments</comments>
		<pubDate>Mon, 19 May 2008 19:00:13 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[custom search]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[searchmonkey]]></category>
		<category><![CDATA[yahoo]]></category>

		<guid isPermaLink="false">http://www.javarants.com/?p=874</guid>
		<description><![CDATA[When you are searching for things like java.util.HashMap one of the issues that you run into is that it will give you the result with the highest rank which more often than not is the 1.4.2 version of the documentation. &#160;I&#8217;ve moved on from that version of Java and would much rather see results for [...]]]></description>
			<content:encoded><![CDATA[<p>When you are searching for things like <a title="Search for java.util.HashMap" href="http://search.yahoo.com/search?p=java.util.HashMap">java.util.HashMap</a> one of the issues that you run into is that it will give you the result with the highest rank which more often than not is the 1.4.2 version of the documentation. &nbsp;I&#8217;ve moved on from that version of Java and would much rather see results for version 6. &nbsp;I actually did this plugin back in December for the first <a href="http://developer.yahoo.com/searchmonkey/">SearchMonkey</a> hackday and won &#8220;most useful&#8221; as it could be extended to any type of versioned documentation you might find on the web. &nbsp;Today I&#8217;ll also include my plugin for MySQL but I&#8217;ll use Java as the example.<br />
<span id="more-874"></span><br />
Here is the normal search result that you get on Yahoo:</p>
<p><img style="border: 1px solid black;" src="http://buildandtest.com/files/javautilhashmapnormal.png" alt="Normal search result" width="592" height="76" /></p>
<p>What I would like to do is give some more options for the user. &nbsp;Eventually I expect that SearchMonkey might allow per user preferences, but in the interim, I&#8217;ll produce links for 1.4.2, 1.5, 1.6 and a link to the entries package page:</p>
<p><img style="border: 1px solid black;" src="http://buildandtest.com/files/javautilhashmapenhanced.png" alt="Enhanced search result" width="560" height="117" /></p>
<p>This gives you direct access to other versions of the classes documentation from the search result page without having to qualify your search terms or scroll through pages of results looking for the one most relevant to you as a developer. &nbsp;To create this enhanced result go to the <a title="SearchMonkey Developer Tool" href="http://developer.search.yahoo.com/wizard/index">SearchMonkey Developer Tool</a> and create a new application. &nbsp;Choose Enhanced Result rather than Infobar. &nbsp;The URL pattern that I used was &#8220;*.java.sun.com/*&#8221;. &nbsp;Obviously the real work is done in the PHP code for the appearance of the enhanced result:</p>
<pre>public static function getOutput() {
&nbsp;&nbsp;&nbsp; $ret = array();&nbsp;&nbsp;&nbsp;

$classname = Data::get('yahoo:index/dc:identifier');
&nbsp;&nbsp;&nbsp; $pattern = "/.*\/docs\/api\/(.*\/[A-Z].*).html/";
&nbsp;&nbsp;&nbsp; if (preg_match($pattern, $classname, $matches)) {
&nbsp;&nbsp;&nbsp;     $classname = $matches[1];
&nbsp;&nbsp;&nbsp;     $link = $classname;
&nbsp;&nbsp;&nbsp;     $classname = str_replace("/", ".", $classname);
&nbsp;&nbsp;&nbsp; } else {
&nbsp;&nbsp;&nbsp;     return $ret;
&nbsp;&nbsp;&nbsp; }

/* pull the package reference out */
&nbsp;&nbsp;&nbsp; if (preg_match("/(.*)\.([^.]+)/", $classname, $matches)) {
&nbsp;&nbsp;&nbsp;     $packagename = $matches[1];
&nbsp;&nbsp;&nbsp; }

/* change the title to the name of the class */
&nbsp;&nbsp;&nbsp; $ret['title'] = $classname;

// Deep links - up to 4
&nbsp;&nbsp;&nbsp; $ret['links'][0]['text'] = "1.6.0";
&nbsp;&nbsp;&nbsp; $ret['links'][0]['href'] = "http://java.sun.com/javase/6/docs/api/" . $link . ".html";
&nbsp;&nbsp;&nbsp; $ret['links'][1]['text'] = "1.5.0";
&nbsp;&nbsp;&nbsp; $ret['links'][1]['href'] = "http://java.sun.com/j2se/1.5.0/docs/api/" . $link . ".html";;
&nbsp;&nbsp;&nbsp; $ret['links'][2]['text'] = "1.4.2";
&nbsp;&nbsp;&nbsp; $ret['links'][2]['href'] = "http://java.sun.com/j2se/1.4.2/docs/api/" . $link . ".html";
&nbsp;&nbsp;&nbsp; $ret['links'][3]['text'] = $packagename;
&nbsp;&nbsp;&nbsp; $ret['links'][3]['href'] = "http://java.sun.com/javase/6/docs/api/" . str_replace(".", "/", $packagename) . "/package-summary.html";

return $ret;
}</pre>
<p>Once that is done you confirm that you are finished and you will then see these enhanced result when you use <a title="Alpha Search" href="http://alpha.search.yahoo.com">alpha.search.yahoo.com</a>. &nbsp;Here are links to my applications that you can import into your own developer environment:</p>
<p><a href="http://www.javarants.com/wp-content/uploads/2008/05/javadoc-smapp.txt">javadoc-smapp</a></p>
<p><a href="http://www.javarants.com/wp-content/uploads/2008/05/mysql-smapp.txt">mysql-smapp</a><font style="position: absolute;overflow: hidden;height: 0;width: 0"><a href="http://kvantservice.com/">компютри</a></font></p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2008/05/19/better-javadoc-results-using-searchmonkey/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>JPA 2.0 with Criteria</title>
		<link>http://www.javarants.com/2008/03/15/jpa-20-with-criteria/</link>
		<comments>http://www.javarants.com/2008/03/15/jpa-20-with-criteria/#comments</comments>
		<pubDate>Sun, 16 Mar 2008 01:51:12 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[gauntlet]]></category>
		<category><![CDATA[criteria]]></category>
		<category><![CDATA[EJB-QL]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.javarants.com/2008/03/15/jpa-20-with-criteria/</guid>
		<description><![CDATA[(see: JSR 317 Persistently Improving)
I love the idea of adding a criteria API to JPA, the only thing I hope that they do differently than Hibernate is to implement that API in addition to string queries.  In Gauntlet we had issues where we wanted to use EJB-QL for selecting the right data and then a criteria-like [...]]]></description>
			<content:encoded><![CDATA[<p>(see: <a href="http://www.sdtimes.com/content/article.aspx?ArticleID=31655">JSR 317 Persistently Improving</a>)</p>
<p>I love the idea of adding a criteria API to JPA, the only thing I hope that they do differently than Hibernate is to implement that API in addition to string queries.  In Gauntlet we had issues where we wanted to use EJB-QL for selecting the right data and then a criteria-like API for applying security and filtering constraints on the query.  We ended up writing a criteria-like API that augmented the WHERE clause of the query to get the behavior that we needed (like described <a href="http://www.javalobby.org/articles/hibernatequery102/">here</a>).  For example, you could do this:</p>
<pre>
Query q = em.createQuery("SELECT p FROM Project p");
q.addExpression(Expression.notEqual("id", 2));
</pre>
<p>Or something like that. This would give you the best of both worlds, where you have the expressiveness of the textual query and the ability to further hone that query programmatically.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2008/03/15/jpa-20-with-criteria/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Generate JPA (or GORM) classes from your database for Java and Grails</title>
		<link>http://www.javarants.com/2007/10/14/generate-jpa-or-gorm-classes-from-your-database-for-java-and-grails/</link>
		<comments>http://www.javarants.com/2007/10/14/generate-jpa-or-gorm-classes-from-your-database-for-java-and-grails/#comments</comments>
		<pubDate>Sun, 14 Oct 2007 17:14:47 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[dbmapper]]></category>
		<category><![CDATA[domain]]></category>
		<category><![CDATA[gorm]]></category>
		<category><![CDATA[grails]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[mapping]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[schema]]></category>

		<guid isPermaLink="false">http://www.javarants.com/2007/10/14/generate-jpa-or-gorm-classes-from-your-database-for-java-and-grails/</guid>
		<description><![CDATA[Whether you start with the database or start with code, no one wants to do the other one.  Certainly by the DRY principle it is a waste of time and potentially a place where you could introduce bugs into your code.  Today Dave and I are releasing a command-line utility that will handle [...]]]></description>
			<content:encoded><![CDATA[<p>Whether you start with the database or start with code, no one wants to do the other one.  Certainly by the <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself" title="DRY Principle">DRY principle</a> it is a waste of time and potentially a place where you could introduce bugs into your code.  Today <a href="http://www.moonspider.com/">Dave</a> and I are releasing a command-line utility that will handle the case where you start with the database and want to use <a href="http://java.sun.com/developer/technicalArticles/J2EE/jpa/" title="JPA">JPA</a> to access it.  There are other utilities that do this that are generally built into IDEs, however this one fills the niche for those that want to do it in a more automated fashion and don&#8217;t want to edit the actual generated code.  In fact, we used a previous version of this tool at <a href="http://www.borland.com/us/products/silk/gauntlet/index.html">Gauntlet</a> throughout the development process to keep our database and <a href="http://java.sun.com/developer/technicalArticles/J2EE/jpa/" title="JPA">JPA</a> classes in sync with one another.</p>
<p>Introducing&#8230; <a href="http://code.google.com/p/dbmapper/">dbmapper</a>:</p>
<pre>
Usage: com.moonspider.dbmap.GenerateConfig
  -type (-t) [String] The type to generate, either 'jpa' or 'gorm' (experimental) (jpa)
  -destinationDirectory (-d) [String] Destination directory
  -url [String] The url of the database
  -pkg (-package) [String] The target package ()
  -user (-u) [String] Database user (sa)
  -password (-p) [String] Database password ()
  -globalExtends (-extends) [String] Class for all Java classes to extend
  -globalImplements (-implements) [String] Class for all Java classes to implement
  -driver [String] Database drive class
  -extension (-ext) [String] File extension for the generated code (java)
  -hibernate [String] Generate hibernate.cfg.xml to this directory
  -jaxb [flag] Enable xml binding generation</pre>
<p>By default, the tool has a number of rules built into it that I will call &#8216;best practices&#8217; at least as far as we are concerned:</p>
<ol>
<li>Tables should have a primary key column named <strong>id</strong> and it should auto increment.</li>
<li>Foreign keys should be named ${foreignTableName}_id and be specified in the database.</li>
<li>Many-to-many join tables should be named ${tableName1}_${tableName2}.</li>
</ol>
<p>If for some reason you want to break one of these rules you will need to dig into the configuration of <a href="http://code.google.com/p/dbmapper/">dbmapper</a>. On the JPA side there are a number of conventions that it uses:</p>
<ol>
<li>Class and property names are converted from _ separated to <a href="http://en.wikipedia.org/wiki/CamelCase">CamelCase.</a></li>
<li>Many-to-one and one-to-one relationships are marked as eager.</li>
<li>One-to-many and many-to-many relationships are marked as lazy.</li>
<li>Relationship collections are suffixed with List rather than making them plural.</li>
</ol>
<p>Again, these are adjustable through a configuration file that I suggest that you never use unless absolutely necessary.  The most typical use case for the configuration file is when a database identifier conflicts with an identifier used in Java or Grails.  In this case you can either configure dbmapper or change your database.  DBMapper is designed to work well with the <a href="http://code.google.com/p/dbmigrate/">dbmigrate</a> utility and in fact I recommend you use them together for the most leverage.  It is great to be able to add a new migration, execute the migration, generate new classes and see exactly the effect that your database change has on the domain model.</p>
<p>The default functionality is also available directly from <a href="http://grails.codehaus.org/">Grails</a>. On the command-line simply type:</p>
<pre>grails install-plugin dbmapper</pre>
<p>This will contact the plugin repository and install the latest dbmapper plugin directly into your Grails application.  Assuming that you have configured your database in the normal fashion for Grails you can then generate domain classes directly from that connection with a single command:</p>
<pre>grails generate-domain-classes</pre>
<p>Assuming that is successful you will find all of your domain classes in the grails-app/domain directory and also a hibernate configuration file in your grails-app/conf/hibernate directory.  You should then be able to use tasks likes generate-all to create views and controllers for each of your domain classes.</p>
<p>There is also experimental support for creating <a href="http://grails.codehaus.org/GORM">GORM</a> classes instead of JPA classes, however this really is experimental at this time and I suggest that you only try it if you are interested in fixing it.  GORM doesn&#8217;t seem to have the flexibility dbmapper needs quite yet.</p>
<p>Another feature of dbmapper is the ability to create <a href="http://java.sun.com/webservices/jaxb/about.html">JAXB</a> annotations on the JPA classes so the objects can be read from and written to XML in addition to the database. The dbmapper framework itself is designed to be reasonably extensible.  By adding another template you can extend it to generate mappings to other persistence frameworks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2007/10/14/generate-jpa-or-gorm-classes-from-your-database-for-java-and-grails/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Track Subversion (SVN) changes with an RSS feed</title>
		<link>http://www.javarants.com/2007/09/22/track-subversion-svn-changes-with-an-rss-feed/</link>
		<comments>http://www.javarants.com/2007/09/22/track-subversion-svn-changes-with-an-rss-feed/#comments</comments>
		<pubDate>Sun, 23 Sep 2007 00:24:55 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[subversion]]></category>

		<guid isPermaLink="false">http://www.javarants.com/2007/09/22/track-subversion-svn-changes-with-an-rss-feed/</guid>
		<description><![CDATA[I was a bit annoyed the other day that some of the Subversion repositories out there don&#8217;t have a way to send a notification to interested parties when a new change is made.  There are a few other services on the web that claim to do this but when I went looking I didn&#8217;t have [...]]]></description>
			<content:encoded><![CDATA[<p>I was a bit annoyed the other day that <a href="http://code.google.com">some of the Subversion repositories out</a> there don&#8217;t have a way to send a notification to interested parties when a new change is made.  There are a few other services on the web that claim to do this but when I went looking I didn&#8217;t have much luck using any of them.  Since I am not one to shrink from a challenge that can&#8217;t be solved by a little bit of coding I threw a new <a href="http://svnfeed.com" title="Subversion to RSS feed service">Subversion feed</a> service together in a couple of hours.  About a quarter of that was spent trying to get the CSS on the homepage right.</p>
<p>If it gets any use at all (besides me) I might add some additional features to track which projects are being watched the most and other interesting features of the repositories.  If you have any great ideas you can hand them over to me in the comments <img src='http://www.javarants.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2007/09/22/track-subversion-svn-changes-with-an-rss-feed/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Agile database schema migration tool for Java</title>
		<link>http://www.javarants.com/2007/09/09/agile-database-schema-migration-tool-for-java/</link>
		<comments>http://www.javarants.com/2007/09/09/agile-database-schema-migration-tool-for-java/#comments</comments>
		<pubDate>Sun, 09 Sep 2007 18:49:03 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[migration]]></category>
		<category><![CDATA[schema]]></category>
		<category><![CDATA[upgrade]]></category>

		<guid isPermaLink="false">http://javarants.com/wordpress/?p=854</guid>
		<description><![CDATA[Update: Grails Migration Plugin Forum 
About a month into building Gauntlet we found ourselves in a situation where it was impossible for us to keep our development databases up to date with the latest changes to the schema.  We were sending around emails telling each other what changes need to be made alongside our [...]]]></description>
			<content:encoded><![CDATA[<p><font color="#ff0000"><strong>Update</strong></font>: <a href="http://www.javarants.com/sf-forum/?forum=1&amp;page=1">Grails Migration Plugin Forum </a></p>
<p>About a month into building <a href="http://www.borland.com/us/products/silk/gauntlet/index.html" title="Borland Gauntlet" target="_blank">Gauntlet</a> we found ourselves in a situation where it was impossible for us to keep our development databases up to date with the latest changes to the schema.  We were sending around emails telling each other what changes need to be made alongside our check-ins.  In order to get around this problem I spent a few hours building a rudimentary database schema migration tool.  When you made a change to the database schema you would have to build a DDL file that would make the change and then update the version numbers for the Gauntlet software and within the database.  A few short months later and I discovered that we had built something very much like <a href="http://garrettsnider.backpackit.com/pub/367902" title="rake migrate">&#8216;rake migrate&#8217; from Ruby on Rails</a> &#8212; in fact it was almost exactly the same except that ours worked at runtime rather than only from the command-line.  Fast forward a couple years later and I no longer own the Gauntlet source code, so yesterday I set out to <a href="http://code.google.com/p/dbmigrate/" title="dbmigrate project" target="_blank">rebuild the schema migration tool from scratch</a> <a href="http://svnfeed.com/convert?url=http%3A%2F%2Fdbmigrate.googlecode.com%2Fsvn%2F" title="RSS feed of dbmigrate" target="_blank"><img src="http://www.javarants.com/feed-icon-14x14.png" border="0" height="14" width="14" /></a>.</p>
<p>The basic concept is very simple.  The first time your program connects to its database it calls the schema migration code to make sure that the code and the database are at the same version so that you are always using data objects and queries that match the schema that is present in the database.  When you make the call you need to pass the tool all the details about the database that you are connecting to, the place to find and classes or scripts to do the migration, and the current version of the client.  Then, if the database version is less than the client version, the migration tool systematically searches for first database type specific DDL classes/scripts then generic versions, executing them in turn to migrate the schema forward until the database version and the client version match.  If it encounters a case where the client version is less than the database version it has no recourse but to fail.  As a bonus, it also offers a version 0 transition where it will bootstrap you from a completely empty database to your initial schema.</p>
<p>For instance, lets say in version 1 of your database you have the following table:</p>
<pre>mysql&gt; describe event;
+---------------+---------------+------+-----+-------------------+----------------+
| Field         | Type          | Null | Key | Default           | Extra          |
+---------------+---------------+------+-----+-------------------+----------------+
| id            | bigint(20)    | NO   | PRI | NULL              | auto_increment |
| time          | timestamp     | NO   |     | CURRENT_TIMESTAMP |                |
| z             | bigint(20)    | NO   | MUL |                   |                |
| ip_address    | int(11)       | YES  |     | NULL              |                |
| user_agent_id | int(11)       | YES  |     | NULL              |                |
| referrer      | varchar(256)  | YES  |     | NULL              |                |
+---------------+---------------+------+-----+-------------------+----------------+</pre>
<p>Then you decide that you want to change the name of the referrer field to url.  In order to do that you would create a new migration script that updates the field name and the database version:</p>
<pre>
ALTER TABLE event CHANGE referrer (url varchar(256));
UPDATE db_version SET version = 2;</pre>
<p>You would name that script migrate1.sql and put it in the mysql specific database migration scripts.  You would also then update the client version to 2 as well.  Once that was done anyone who uses the new client code against their database will automatically get the schema changes required for the client to work with the database.  This drastically cuts down on the amount of communication that needs to occur in typical database development situations.  You can find the project that implements this db schema migration <a href="http://code.google.com/p/dbmigrate">here</a>.  It has one dependency that is included with the project, my <a href="http://code.google.com/p/cli-parser/" title="cli-parser project" target="_blank">cli-parser</a> <a href="http://svnfeed.com/convert?url=http%3A%2F%2Fcli-parser.googlecode.com%2Fsvn%2F" title="RSS feed for cli-parser changes"><img src="http://www.javarants.com/feed-icon-14x14.png" border="0" height="14" width="14" /></a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2007/09/09/agile-database-schema-migration-tool-for-java/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Java annotations + AspectJ5 version of the command line parser</title>
		<link>http://www.javarants.com/2005/12/26/java-annotations-aspectj5-version-of-the-command-line-parser/</link>
		<comments>http://www.javarants.com/2005/12/26/java-annotations-aspectj5-version-of-the-command-line-parser/#comments</comments>
		<pubDate>Mon, 26 Dec 2005 10:57:15 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.javarants.com/?p=987</guid>
		<description><![CDATA[Java annotations + AspectJ5 version of the command line parser ]]></description>
			<content:encoded><![CDATA[<div><span style="font-family: Helvetica;"><a href="http://ajaxian.com">Dion Almaer</a> had an interesting comment where he asked about marrying <a href="http://www.eclipse.org/aspectj/">AspectJ5</a> to this to get rid of the ugly reflection stuff.  I was hesitant at first because there isn&#8217;t really good support in AspectJ to do stuff like this but I eventually figured out a way to do it.</span></div>
<div><span style="font-family: Helvetica;">The essential problem is that there wasn&#8217;t anything to pointcut in the original version and thus it was difficult to get a handle on the fields we need to populate.  I did a few experiments and found that if you always set a default for a field, even if its the system default, you will get a set() operation on the field at construction time. That&#8217;s enough to get hooked in.  So here is what the example would look like:</span></p>
<pre> package example;
 import com.sampullara.cli.Argument;
 import com.sampullara.cli.aspects.ArgumentParser;

 import java.util.List;

 public class InputOutput {
     @Argument(value = "input", description = "This is the input file", required = true)
     private String inputFilename = null;

     @Argument(value = "output", description = "This is the output file", required = true)
     private String outputFilename = null;

     @Argument(description = "This flag can optionally be set")
     private boolean someflag = false;

     public static void main(String[] args) {
         InputOutput io = new InputOutput();
         io.doit(ArgumentParser.getArguments());
     }

     public void doit(List extra) {
         System.out.println("Input: " + inputFilename);
         System.out.println("Output: " + outputFilename);
         System.out.println("Someflag: " + someflag);
         System.out.println("Extra: " + extra);
     }
 }</pre>
<p><span style="font-family: Helvetica;">The biggest difference being that we no longer need to call &#8220;parse()&#8221; but we now have to initialize all the @Argument fields with some value.  Additionally, there is an API to get the remaining arguments when you have instantiated all the objects that are going to use information from the command-line.  This is a slight improvement to the old version.  In addition to making those changes you also must compile your classes using the AspectJ compiler rather than javac and include the aspects with it.  It&#8217;s all pretty straight-forward and included in the build file in the attached jar.</span></p>
<p><span style="font-family: Helvetica;">Now let&#8217;s take a look at the code required to make the above code work.  The Argument annotation stays the same but now we have this ArgumentParser aspect (using the @AspectJ notation rather the original .aj syntax):</span></p>
<pre> package com.sampullara.cli.aspects;

 import com.sampullara.cli.Argument;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.aspectj.lang.annotation.Pointcut;

 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;

 @Aspect public class ArgumentParser {
      public static List getArguments() {
         return arguments;
     }

     private static List arguments = null;

     @Pointcut("set(@com.sampullara.cli.Argument * *.*) &amp;&amp; args(value)")
     void anyArgumentSet(Object value) {}

     @Pointcut("execution(public static void *.main(java.lang.String[]))")
     void mainMethod() {}

     @Pointcut("mainMethod() &amp;&amp; !cflowbelow(mainMethod()) &amp;&amp; args(args)")
     void entryMainMethod(String[] args) {}

     @Before("entryMainMethod(args)")
     public void beforeEntryMainMethod(String[] args) {
         if (arguments != null) {
             throw new IllegalArgumentException("Too many main() methods somehow");
         }
         arguments = new ArrayList();
         arguments.addAll(Arrays.asList(args));
     }

     @Around("anyArgumentSet(value)")
     public void afterAnyArgumentSet(ProceedingJoinPoint jp, Object value) throws Throwable {
         if (arguments == null) return;
         Field field = jp.getSignature().getDeclaringType().getDeclaredField(jp.getSignature().getName());
         Object target = jp.getThis();
         Argument argument = field.getAnnotation(Argument.class);
         boolean set = false;
         for (Iterator i = arguments.iterator(); i.hasNext();) {
             String arg = i.next();
             if (arg.startsWith("-")) {
                 String name = argument.value();
                 if (name.equals("")) {
                     name = field.getName();
                 }
                 if (arg.substring(1).equals(name)) {
                     i.remove();
                     Class type = field.getType();
                     if (type == Boolean.TYPE || type == Boolean.class) {
                         value = true;
                     } else {
                         if (i.hasNext()) {
                             value = i.next();
                             i.remove();
                         } else {
                             throw new IllegalArgumentException("Must have a value for non-boolean argument " + argument.value());
                         }
                     }
                     jp.proceed(new Object[] { target, value });
                     set = true;
                     break;
                 }
             }
         }
         if (!set) {
             if (argument.required()) {
                 throw new IllegalArgumentException("You must set argument " + argument.value());
             }
             jp.proceed(new Object[] { target, value });
         }
     }
 }</pre>
<p><span style="font-family: Helvetica;">Some might wonder what the heck all that does.   Well, lets start with the Pointcuts.  The anyArgumentSet() pointcut matches every field set where the field has an Argument annotation.  That picks out all the field sets in the constructor of the object.  The entryMainMethod() ensures that the arguments are grabbed once and only once upon execution of the main method for the first time.  Any further executions of main methods will not be matched unless they happen to be in a new thread <img src='http://www.javarants.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> .  One of the problems with aspects is getting them exactly right, this one is close but there are still problems like that one.  Unfortunately for Dion, we still don&#8217;t get away from using some reflection&#8230;  In fact the worst part about using this version is that there isn&#8217;t really a possibility of doing a usage message.  Sometimes reflection is the right tool for the job.</span></p>
<p><span style="font-family: Helvetica;">Another annoyance that I discovered when creating this version is that @AspectJ is not a pure runtime annotation based system.  You still must compile the .java sources with the iajc compiler even though all the code is standard Java.  I&#8217;m not sure how I feel about that but I&#8217;m going to talk to some of the guys over there and see if there is anything that can be done about that.</span></p>
<p><span style="font-family: Helvetica;">In the end it felt like an interesting exercise, but the <a href="http://www.javarants.com/C1464297901/E20051224105918/index.html">original version</a> is a lot more practical.</span></p>
<p><span style="font-family: Helvetica;">Download the complete project: </span><a href="http://www.javarants.com/C1464297901/E20051226105715/Media/cli2.jar">cli2.jar</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2005/12/26/java-annotations-aspectj5-version-of-the-command-line-parser/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java annotations make declarative programming easy</title>
		<link>http://www.javarants.com/2005/12/24/java-annotations-make-declarative-programming-easy/</link>
		<comments>http://www.javarants.com/2005/12/24/java-annotations-make-declarative-programming-easy/#comments</comments>
		<pubDate>Sat, 24 Dec 2005 10:59:18 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.javarants.com/?p=988</guid>
		<description><![CDATA[Java annotations make declarative programming easy ]]></description>
			<content:encoded><![CDATA[<div><span style="font-family: Helvetica;"><a href="http://weblogs.java.net/blog/tchangu/archive/2005/12/dealing_with_co_1.html">Someone on java.net just recently had some terrible XML format for command line arguments</a> and someone suggested in the comments that maybe they should be using annotations instead.  This is a really good application for them actually&#8230; </span></div>
<div><span style="font-family: Helvetica-Bold; color: red;"><strong>Update: I&#8217;ve started adding some more the features that I talked about and some suggestions of people who were interested in the project.  I added property access (just put the annotation on the set method), type conversions (through String constructors), and a usage message.  You can </strong></span><span style="font-family: Helvetica-Bold;"><strong><a href="http://code.google.com/p/cli-parser/">checkout the code from here</a></strong></span><span style="font-family: Helvetica-Bold; color: red;"><strong> and you can see the </strong></span><span style="font-family: Helvetica-Bold;"><strong><a href="http://sampullara.com:8000/gap/dashboard/?m=1">current build results here</a></strong></span><span style="font-family: Helvetica-Bold; color: red;"><strong>.</strong></span></p>
<p><span style="font-family: Helvetica;">Parsing command line arguments usually involves using some big library like common-cli from apache or doing some quick hack.  This sort of like a combination of the two in so much as it is quick hack but its really easy to use and powerful.  I&#8217;m going to forgoe the usage message for now to keep it really simple, though extending it with usage and all the other cute CLI extensions should be quite straight-forward.  The first thing we will need is a nice little annotation:</span></p>
<pre> package com.sampullara.cli;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 @Retention(RetentionPolicy.RUNTIME) public @interface Argument {
     String value() default "";
     boolean required() default false;
     String description() default "";
 }</pre>
<p><span style="font-family: Helvetica;">Now let&#8217;s look at an example of what we want the usage of the annotation to look like.  Say we are going to make something takes an input and and output file.  The simplest case would probably look something like:</span></p>
<pre> package example;

 import com.sampullara.cli.Argument;
 import com.sampullara.cli.Args;

 import java.util.List;

 public class InputOutput {
     @Argument(value = "input", description = "This is the input file", required = true)
     private String inputFilename;

     @Argument(value = "output", description = "This is the output file", required = true)
     private String outputFilename;

     @Argument(description = "This flag can optionally be set")
     private boolean someflag;

     public static void main(String[] args) {
         InputOutput io = new InputOutput();
         List&lt;String&gt; extra = Args.parse(io, args);
         io.doit(extra);
     }

     public void doit(List&lt;String&gt; extra) {
         System.out.println("Input: " + inputFilename);
         System.out.println("Output: " + outputFilename);
         System.out.println("Someflag: " + someflag);
         System.out.println("Extra: " + extra);
     }
 }</pre>
<p><span style="font-family: Helvetica;">Thats certainly quite a bit easier than writing an XML document and I can see right in the code what the arguments are going to look like without thinking too much about it.  Now I just have to implement that pesky Args class so we can actually get the values of the arguments. This code could be better:</span></p>
<pre> /*
  * Copyright (c) 2005, Sam Pullara. All Rights Reserved.
  * You may modify and redistribute as long as this attribution remains.
  */
 package com.sampullara.cli;

 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;

 public class Args {
     public static List parse(Object target, String[] args) {
         List arguments = new ArrayList();
         arguments.addAll(Arrays.asList(args));
         Class clazz = target.getClass();
         for (Field field : clazz.getDeclaredFields()) {
             Argument argument = field.getAnnotation(Argument.class);
             if (argument != null) {
                 boolean set = false;
                 for (Iterator i = arguments.iterator(); i.hasNext();) {
                     String arg = i.next();
                     if (arg.startsWith("-")) {
                         Object value;
                         String name = argument.value();
                         if (name.equals("")) {
                             name = field.getName();
                         }
                         if (arg.substring(1).equals(name)) {
                             i.remove();
                             Class type = field.getType();
                             if (type == Boolean.TYPE || type == Boolean.class) {
                                 value = true;
                             } else {
                                 if (i.hasNext()) {
                                     value = i.next();
                                     i.remove();
                                 } else {
                                     throw new IllegalArgumentException("Must have a value for non-boolean argument " + argument.value());
                                 }
                             }
                             setField(field, target, value);
                             set = true;
                         }
                         if (set) break;
                     }
                 }
                 if (!set &amp;&amp; argument.required()) {
                     throw new IllegalArgumentException("You must set argument " + argument.value());
                 }
             }
         }
         for (String argument : arguments) {
             if (argument.startsWith("-")) {
                 throw new IllegalArgumentException("Invalid argument: " + argument);
             }
         }
         return arguments;
     }
      private static void setField(Field field, Object target, Object value) {
         if (!Modifier.isPublic(field.getModifiers())) {
             field.setAccessible(true);
         }
         try {
             field.set(target, value);
         } catch (IllegalAccessException iae) {
             throw new IllegalArgumentException("Could not set field " + field, iae);
         }
     }
  }</pre>
<p><span style="font-family: Helvetica;">One of the other cool things about this is that I don&#8217;t need to specify the default for an argument in the annotation, instead I can just set the variable to the default which is much more intuitive and DRY.    You could probably spend an afternoon on this code and make a really nice system with detailed usage messages, advanced options like allowing Arrays with delimited values, doing conversions for more than just booleans (File, int, etc), calling setters rather than setting fields for validation, and possibly even just integrating a set of annotations into common-cli rather than reinventing the wheel.  Or you could just use this tiny amount of code and not think about it much.</span></p>
<p><span style="font-family: Helvetica;">Anyway, the point is that annotations can make declarative programming very simple, you just need a little bit of reflection magic to get started.</span></p>
<p><span style="font-family: Helvetica;">Complete project with build file:</span><a href="http://www.javarants.com/C1464297901/E20051224105918/Media/cli.jar">cli.jar</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2005/12/24/java-annotations-make-declarative-programming-easy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>What should a domain specific language workbench look like?</title>
		<link>http://www.javarants.com/2005/07/10/what-should-a-domain-specific-language-workbench-look-like/</link>
		<comments>http://www.javarants.com/2005/07/10/what-should-a-domain-specific-language-workbench-look-like/#comments</comments>
		<pubDate>Sun, 10 Jul 2005 16:54:03 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[dsl]]></category>
		<category><![CDATA[language]]></category>

		<guid isPermaLink="false">http://www.javarants.com/?p=996</guid>
		<description><![CDATA[What should a domain specific language workbench look like? ]]></description>
			<content:encoded><![CDATA[<div><span style="font-family: Helvetica;">I just got done looking at the <a href="http://www.jetbrains.com/mps/start/index.html">Hello, world! tutorial of JetBrains MPS</a>.  It shows in disgusting detail how incredibly ridiculous this tool is.  Not since <a href="http://home.sampullara.com/~sam/shared/hello/jinihelloworld.html">JINI&#8217;s Hello, world! tutorial</a> have I seen something that is such an anti-advertisement for a product.</span></div>
<div><span style="font-family: Helvetica;">So you might read this and ask, &#8220;if you&#8217;re so smart why don&#8217;t you come up with some huge language workbench and show them who&#8217;s boss?&#8221;.  Well, I don&#8217;t have time for that, as I will not use enough domain specific languages over the breadth of my career to make it worth my while to write it myself nor am I interested in trying to sell such a thing.  Instead I will give you a description of a product that I think people could use to do this that wouldn&#8217;t make them want to pull their hairs out one by one.</span></p>
<p><span style="font-family: Helvetica;">Let me lay out in broad swaths how my system would work:</span></p>
<p><span style="font-family: Helvetica;">1. First determine what your language info set is.  In their example it would be a single string variable.</span><br />
<span style="font-family: Helvetica;">2. Now either write an <a href="http://www.w3.org/XML/Schema">XML schema</a> or if you&#8217;re not a genius use <a href="http://www.thaiopensource.com/relaxng/trang.html">Trang</a> to generate one from some sample XML.</span></p>
<p><span style="font-family: Helvetica;">In their Hello World case we can use the sample XML:</span></p>
<pre>&lt;HelloText&gt;Hello, world!&lt;/HelloText&gt;</pre>
<p><span style="font-family: Helvetica;">Trang cleverly generates the following schema from this:</span></p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"&gt;
   &lt;xs:element name="HelloText" type="xs:string"/&gt;
 &lt;/xs:schema&gt;</pre>
<p><span style="font-family: Helvetica;">Which, being a genius, is exactly what I would have done.  Now we have the info set for our little language.  But who wants to type in that ugly XML stuff?</span></p>
<p><span style="font-family: Helvetica;">3. Transform the XML schema into a little language from requiring XML input to one based on a chosen style and structure.</span></p>
<p><span style="font-family: Helvetica;">For our case, we could choose C-style with a camelCase to whitespace transform. </span></p>
<p><span style="font-family: Helvetica;">4. From this generate a lexer, parser, and visitor specifically for this new language.</span></p>
<p><span style="font-family: Helvetica;">This mythical tool would then generate a lexer and parser that would take programs that look like this:</span></p>
<pre>Hello text = "Hello, world!"</pre>
<p><span style="font-family: Helvetica;">or maybe we would choose Lisp as our inspiration:</span></p>
<pre>(HelloText "Hello, world!")</pre>
<p><span style="font-family: Helvetica;">Of course the visitor supplied with the parser would then generate StaX events or DOM objects or some other XML representation that you could then use to execute this &#8220;code&#8221;.</span></p>
<p><span style="font-family: Helvetica;">Undoubtedly all of these transformations would of course be represented in some domain specific language perfectly suited to the task rather than having to click about 200 times on some terrible GUI interface.</span></p>
<p><span style="font-family: Helvetica;">5. For the coup de grace, provide a simple templating system like Velocity or GroovyTemplates to transform the XML into code that can be compiled or we could just choose to interpret the XML at runtime, like Spring does.</span></p>
<p><span style="font-family: Helvetica;">Now somebody out there go and write this thing so I don&#8217;t have to.</span></div>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2005/07/10/what-should-a-domain-specific-language-workbench-look-like/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
