<?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>Wed, 21 Jul 2010 17:36:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>HAvroBase: a searchable, evolvable entity store on top of HBase and Solr</title>
		<link>http://www.javarants.com/2010/06/30/havrobase-a-searchable-evolvable-entity-store-on-top-of-hbase-and-solr/</link>
		<comments>http://www.javarants.com/2010/06/30/havrobase-a-searchable-evolvable-entity-store-on-top-of-hbase-and-solr/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 19:55:44 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Startup]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1349</guid>
		<description><![CDATA[Building out a social consumer internet product that could change quickly and evolve over time puts special requirements on the underlying data store. You need to be prepared for scale but not investing too much too early, your business may &#8230; <a href="http://www.javarants.com/2010/06/30/havrobase-a-searchable-evolvable-entity-store-on-top-of-hbase-and-solr/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Building out a social consumer internet product that could change quickly and evolve over time puts special requirements on the underlying data store. You need to be prepared for scale but not investing too much too early, your business may need to pivot in different directions so data models can&#8217;t be set in stone and you need to be able to search that data to enable many of the features users expect from an online social product. I have the additional requirement that I wanted all the entities in the system, regardless of where they are stored, to be accessed the same way and be described by the same data description language for consistency and maintainability. I&#8217;ve created what I think to be a novel solution to these requirements in the form of <a href="http://github.com/spullara/havrobase">HAvroBase</a>.<span id="more-1349"></span></p>
<p>The first choice you have to make against these requirements is which data definition language are you going to use? Instead of depending on the native format of the storage system I&#8217;ve decided to use <a href="http://github.com/apache/avro">Avro</a>. Similar to <a href="http://code.google.com/p/protobuf/">Protocol Buffers</a> and <a href="http://incubator.apache.org/thrift/">Thrift</a>, Avro lets you define your entities using schemas and store them efficiently in a binary format. Additionally, as long as you have the original schema available you can load old data into a new schema. This will let you evolve your stored rows lazily and not have to completely update your storage system when a new field is added or a field is removed.</p>
<p>Whereas the data definition choice is basically commodity at this point and your choice can be somewhat arbitrary, the choice of storage technology will likely be something that has more trade-offs to consider. After looking at the features and communities of a variety of projects including <a href="http://hbase.apache.org/">HBase</a>, <a href="http://cassandra.apache.org/">Cassandra</a>, <a href="http://code.google.com/p/redis/">Redis</a>, <a href="https://wiki.basho.com/display/RIAK/Riak">Riak</a>, <a href="http://mysql.com">MySQL</a>, <a href="http://www.northscale.com/products/membase_server.html">Membase</a>, <a href="http://www.terracotta.org/">Terracotta</a>, etc. I finally chose HBase for a few reasons that may not be that important to you. First I settled on a <a href="http://labs.google.com/papers/bigtable.html">BigTable</a> type choice based on the data model. That left HBase and Cassandra as contenders. There also a few things I think are advantages:</p>
<ul>
<li>multiple tables</li>
<li>better ordered key support</li>
<li>Zookeeper and HDFS were already in my solution</li>
<li>Hive and Hadoop support against the native data format</li>
<li>consistency</li>
<li>compare and set</li>
<li>atomic increment</li>
<li>versioning</li>
</ul>
<p><span style="font-family: Georgia, 'Bitstream Charter', serif; line-height: 24px; font-size: 16px;">Cassandra definitely has its own advantages that didn&#8217;t out-weigh the other considerations including</span></p>
<ul>
<li>performance</li>
<li>simple deployment</li>
<li>always writable</li>
</ul>
<p><span style="font-size: medium;"><span style="line-height: 24px;">You might make different tradeoffs or even use both solutions for different problems. I&#8217;m also biased somewhat as I am sharing an office with <a href="http://cloudera.com/">Cloudera</a> and get top notch support at a moments notice.</span></span></p>
<p><span style="font-size: medium;"><span style="line-height: 24px;">Whether I chose HBase or Cassandra the implementation would have been much the same and with the HAvroBase framework you can have multiple independent storage systems. The framework does somewhat shield you from this decision, at least in your code.</span></span></p>
<p><span style="font-size: medium;"><span style="line-height: 24px;">When it comes to text search you really don&#8217;t get better than <a href="http://lucene.apache.org/">Lucene</a> in open source and the features that <a href="http://wiki.apache.org/solr/FrontPage">Solr</a> builds on top of Lucene make it even better. I don&#8217;t think there is reasonable argument for using something besides Solr at this point. Especially with their support for sharding and replication that comes with <a href="http://wiki.apache.org/solr/SolrCloud">Solr Cloud</a>. It also has the nice benefit that it supports multiple tables, like HBase, so I can efficiently separate entities and allow them to scale independently without managing an additional system.</span></span></p>
<p><span style="font-size: medium;"><span style="line-height: 24px;">The last choice that I made was runtime configuration. There are a few solutions including <a href="http://www.springsource.org/">Spring</a>, <a href="http://code.google.com/p/google-guice/">Guice</a> and rolling my own and I finally landed on the side of Guice. I just like typed, programmatic configuration better than XML files and since that is the focus of Guice, I think it is the best solution for that.</span></span></p>
<p><span style="font-size: medium;"><span style="line-height: 24px;">The first thing that you need to do to use the system is to define an entity in Avro:</span></span><br />
<script src="http://gist.github.com/484813.js"></script><br />
<span style="font-size: small;"><span style="font-size: medium;"><span style="line-height: 24px;">You can use the Avro compiler (or the Maven plugin) to convert that definition to classes (HAvroBase requires this). Then you do the typical things in code to setup your HBase connection but within a Guice module and set some of the configuration parameters for HAB:</span></span></span><br />
<script src="http://gist.github.com/484810.js"></script><br />
<span style="font-size: small;"><span style="font-size: medium;"><span style="line-height: 24px;">That configuration can then be used to instantiate an instance of the HAB class that implements the connection to HBase like this:</span></span></span><br />
<script src="http://gist.github.com/484815.js"></script><br />
<span style="font-size: small;"><span style="font-size: medium;"><span style="line-height: 24px;">You&#8217;ll notice that configuration is somewhat split between things that the base system needs to know and things that the HAB needs to know. For example, what table the schema is store in isn&#8217;t relevant to the base system as an implementer is free to store schemas however they like. But the assumption is that every system will have the concept of a table and a column family in order to separate entities in the underlying storage system. The Solr support is pretty elegant I think. Rather than specifying in more than one place which fields should be indexed, instead at runtime it queries the Solr core&#8217;s schema.xml that defines them and then when you put an entity in the system it automatically indexes those fields.  Here is an example of using some of the APIs:</span></span></span><br />
<script src="http://gist.github.com/484816.js"></script><br />
This example creates a new User, puts it into the HAvroBase, looks it up by row and then searches for it by field that is indexed and finally deletes it. In any fully implemented AvroBase system this should work identically. You&#8217;ll notice in the memcached implementation that only put/get/delete are implemented and it doesn&#8217;t support scan or search at all. I&#8217;ve considered breaking out that functionality into separate interfaces but haven&#8217;t done that yet.</p>
<p>If you are unhappy with the way the default Avro compiler generates code you can use my <a href="http://github.com/spullara/avrocompiler">templated Avro compiler</a> that lets you change the generated code. I have done that for my project to make them a little more developer friendly.</p>
<p>Things left to do:</p>
<ul>
<li>implement guarantees around indexing</li>
<li>optimize schema keys (use an abbrev table instead of a hex sha-256 key)</li>
<li>indexing nested fields and arrays in Solr</li>
</ul>
<p>I&#8217;m sure there are more things left undone but those are some of the more obvious issues.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/06/30/havrobase-a-searchable-evolvable-entity-store-on-top-of-hbase-and-solr/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Static-typing is a powerful metadata database, exploit it!</title>
		<link>http://www.javarants.com/2010/06/16/static-typing-is-a-powerful-metadata-database-exploit-it/</link>
		<comments>http://www.javarants.com/2010/06/16/static-typing-is-a-powerful-metadata-database-exploit-it/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 00:20:47 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1331</guid>
		<description><![CDATA[Today someone decided to pretend they knew something about how a modern statically typed language developer works.  Perhaps they are big emacs fans or something because they felt that static-types leading to autocomplete in an IDE was somehow a feature &#8230; <a href="http://www.javarants.com/2010/06/16/static-typing-is-a-powerful-metadata-database-exploit-it/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Today someone decided to pretend they knew something about how a modern statically typed language developer works.  Perhaps they are big emacs fans or something because they felt that static-types leading to autocomplete in an IDE was somehow a feature in the language FOR THE IDE.  The IDE gets no benefit, in fact, editors like emacs and TextMate are much simpler. But I can tell you that the developer gets a tremendous benefit by having this metadata database not only present in the code and easily queryable but heavily exploited by her tools.  What is amazing about this metadata database is that it is actually populated by that same IDE.  There are very few times that I even type a Type &#8212; 90% of those times are when declaring a new Type &#8212; the rest of the time the IDE is very patiently maintaining and leveraging that database for me.  Even better, when someone else is looking at the source code, or even using the library, they instantly get 80% of the documentation. All that is left are the semantics of the calls. Perhaps we need to have some sort of meetup where we look over each others shoulders and actually understand how someone who is on the other side really works rather than dynamic-typing language people assuming that the programmer is maintaining the huge metadata database present in the static-typing language developers code.  And on the otherside that static-typers are assuming that the dynamic-typing language developer is memorizing all kinds of arcane method call names, argument shapes and the shapes of all the libraries they are using. Do you really memorize all that trivia?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/06/16/static-typing-is-a-powerful-metadata-database-exploit-it/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Building the ideal web application template engine</title>
		<link>http://www.javarants.com/2010/06/16/building-the-ideal-web-application-template-engine/</link>
		<comments>http://www.javarants.com/2010/06/16/building-the-ideal-web-application-template-engine/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 18:02:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1327</guid>
		<description><![CDATA[A month and a half ago I had put out a call for what I was calling the &#8216;ideal web application template engine&#8216; along with a list of requirements that I thought would be present in such a system.  Since &#8230; <a href="http://www.javarants.com/2010/06/16/building-the-ideal-web-application-template-engine/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A month and a half ago I had put out a call for what I was calling the &#8216;<a href="http://www.javarants.com/2010/05/03/the-ideal-web-application-templating-system/">ideal web application template engine</a>&#8216; along with a list of requirements that I thought would be present in such a system.  Since then I looked a bunch of them and decided that I like the simple markup that <a href="http://mustache.github.com/">mustache</a> defined but none of the implementations were up to doing what I wanted.  This led me to embark on building a new engine with for that markup for my chosen platform, Java, which I called creatively, <a href="http://github.com/spullara/mustache.java">mustache.java</a>.  Though it claims to be &#8216;logic-less&#8217; I would say that it has some amount of logic. It will loop over a set of objects and it will check booleans, but I think it is about as close to logic-less as you would want to be in a template language.  So, let&#8217;s look at each of the requirements and how I ended up implementing them:<br />
<span id="more-1327"></span></p>
<ul>
<li><em>Works well with HTML5/CSS3 progressive enhancement</em></li>
</ul>
<p>This one is straight-forward.  Because I put no limitations on the generated text you can actually generate almost anything with mustach.java, in fact, I am using it in another <a href="http://github.com/spullara/avrocompiler">project</a> to generate Java source for Avro objects.  It is really overkill for that project but it is so easy to use that I used it anyway.</p>
<ul>
<li><em>Allows mock data within the template that is replaced at runtime</em></li>
<li><em>Client-side version that leverages the mock data for shift-reload debugging</em></li>
</ul>
<p>These I implemented somewhat differently from the requirement because the mustache template language is not tag based.  I have actually thought about whether it might make sense to make it tag-based and get the full requirement, but I digress.  What I did get to is a system that is easy for a frontend developer or designer to use without having the whole system running on their machine.  Included with mustache.java is a mini-server (called <strong>handlebar</strong>, thanks for the name <a href="http://lukew.com">Luke</a>) that combines mock json data with mustache.java templates. This lets them view a fully rendered version of the page they are working on with the required templating information that will be used in production but without running a big production system. In fact, because mustache.java dynamically generates and compiles Java code, they can fire up <strong>handlebar</strong> in directory along with their mock data and just keep reloading the page to see the effect of changes they make.</p>
<ul>
<li><em> Composable components, not monolithic pages</em></li>
<li><em><em>Very little or no business logic in the templates</em></em></li>
</ul>
<p>The choice of mustache as a base template language ensured that this would be the case.  Including a partial within a template is easy and makes pages very easy to compose. I still miss the Django template style <em>extends/block</em> system and may extend mustache to support it. Having to remember to include things like the header and footer on every page doesn&#8217;t seem necessary.  As I said above, I think that mustache has the minimum reasonable logic.</p>
<ul>
<li><em>Concurrent evaluation possible</em></li>
</ul>
<p>This one was very important to me from a performance perspective. My implementation makes every effort to be as low latency as possible for the end user.  At every possible point in template evaluation things are actually executed in separate threads or purely asynchronously in the case of external I/O like HTTP requests to other services.  The one last thing I am going to do here is to allow not only a straight-line evaluation of the template but the possibility of specifying a timeout so that you can return different markup if evaluation doesn&#8217;t return in time. It may be unnecessary to have this in the base template engine though, still looking at the design of the feature.</p>
<p>So how easy is using the template system?  I think I can answer that question by looking at the relevant portions of the <a href="http://github.com/spullara/mustache.java/blob/master/handlebar/src/main/java/com/sampullara/mustache/Handlebar.java">implementation of </a><strong><a href="http://github.com/spullara/mustache.java/blob/master/handlebar/src/main/java/com/sampullara/mustache/Handlebar.java">handlebar</a>:</strong></p>
<pre>final MustacheCompiler mc = new MustacheCompiler(new File("."));
....
Mustache mustache = mc.compile(new BufferedReader(new FileReader(filename)));
FutureWriter fw = new FutureWriter(res.getWriter());
File file = new File(mocks, base + ".json");
if (file.exists()) {
  BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
  JsonParser parser = jf.createJsonParser(bis);
  JsonNode json = parser.readValueAsTree();
  mustache.execute(fw, new Scope(json));
} else {
  mustache.execute(fw, new Scope());
}
fw.flush();</pre>
<p>The most interesting part of this is the FutureWriter. The future writer lets mustache write evaluated templates completed out of order in template order.  The scope is essentially a sophisticated context object that knows how to pull data from Java objects of various types, including raw object fields and methods, Maps and Json objects. Conveniently, you can also store values in it directly. There are some things I would like to extend at some point, however, for all practical purposes the template system is finished.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/06/16/building-the-ideal-web-application-template-engine/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Android Dalvik VM performance is a threat to the iPhone</title>
		<link>http://www.javarants.com/2010/05/26/android-dalvik-vm-performance-is-a-threat-to-the-iphone/</link>
		<comments>http://www.javarants.com/2010/05/26/android-dalvik-vm-performance-is-a-threat-to-the-iphone/#comments</comments>
		<pubDate>Wed, 26 May 2010 16:29:57 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1311</guid>
		<description><![CDATA[One of the peculiarities of Apple is that they have set themselves down a path where every Apple developer needs to learn Objective-C (and C/C++) to build applications for their platform.  The biggest characteristic of Objective-C vs Java is dynamic &#8230; <a href="http://www.javarants.com/2010/05/26/android-dalvik-vm-performance-is-a-threat-to-the-iphone/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the peculiarities of Apple is that they have set themselves down a path where every Apple developer needs to learn Objective-C (and C/C++) to build applications for their platform.  The biggest characteristic of Objective-C vs Java is dynamic dispatch. At runtime Objective-C can send arbitrary messages to objects and they may or may not respond to them.  This has the nice property that you can write code that is very dynamic and loosely bound but it also has the property that method calls in Objective-C are very slow and the more code that you write in Objective-C instead of in C/C++ the slower your codebase becomes.  Up until Android 2.2 (Froyo) the JVM (really a <a href="http://en.wikipedia.org/wiki/Dalvik_(software)">Dalvik JVM</a> for licensing reasons) on the Android platform was playing with one hand tied behind its back.  Different from desktop/server Java, the JVM was still an interpreter, like the original JVM back in the Java 1.0 days.  It was very efficient interpreter but an interpreter none-the-less and was not creating native code from the Dalvik bytecodes that it uses.  As of Android 2.2 they have added a JIT, a just-in-time compiler, to the stack that translates the Dalvik bytecode into much more efficient machine code much like a C/C++ compiler.  You can see the results of this in the benchmarks of Froyo which <a href="http://crave.cnet.co.uk/mobiles/0,39029453,49305763,00.htm">show a 2-5x improvement</a>.  As they add more and more JIT and GC features that have appeared in HotSpot, JRockit, etc, you will likely see even more improvements over time &#8212; without having to change or recompile the 3rd party developed software.</p>
<p><span id="more-1311"></span></p>
<p>This wouldn&#8217;t be that big a deal if Android software wasn&#8217;t already approaching the speed of the Apple iPhone even when running its applications through the interpreter (see the HTC EVO 4G running 2.1).  This is likely going to mean that 3rd party developer applications created for Android, running on the same hardware, is going to be faster than the same code written against the Objective-C libraries that Apple provides for the iPhone.  You&#8217;ll be able to get more done, have smoother user interfaces and all around build more powerful applications easier.  A better experience for the user and the developer on Android is a bad thing for Apple.</p>
<p>The final issue that Apple has is that far more people know and need  to know Java than Objective-C.  Except for their platform, there is no need to ever learn it.  The tool chain is much more robust, information is much easier to come by, garbage collection is available, and there are thousands more libraries written in Java than Objective-C and far more portable libraries than are written for C/C++.  You might argue that you can always drop down to C/C++ code to make up for the lost performance of using Objective-C (at a significant cost development-wise).  You can do that, except places where you need to make a call into Apple&#8217;s Objective-C runtime libraries or where you want to write callbacks from those libraries. Those are mostly Objective-C libraries and use the dynamic dispatch mechanism which <a href="http://www.javarants.com/2004/05/04/looks-like-apple-should-switch/">I showed in 2004 was very much slower than Java</a>.  I&#8217;d really love to see the whole <a href="http://shootout.alioth.debian.org/">computer language shootout</a> written with Objective-C calling conventions just to show how much slower it is at that level.</p>
<p>Obviously performance is not the only consideration, but it is a big one.  Android has other issues like a fragmented operating system base, hardware feature base and a more complicated user experience.  All those things will conspire to hold it back but I think we can see the writing on the wall that Android is going to dominate iPhone market-share wise which will eventually make it a more attractive platform business-wise.</p>
<p><strong>Update: </strong>Just so people don&#8217;t get the wrong idea, I am a rabid iPhone user and develop for the iPhone first.  This blog entry is to call out a threat that Apple should take seriously.</p>
<p><strong>Update 2: </strong>Alright, you win. Don&#8217;t worry about competing with Google &amp; Android on performance. It probably doesn&#8217;t matter that much for the user experience.  Especially don&#8217;t fix obj_msgSend() with a JIT/LLVM, that would be crazy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/05/26/android-dalvik-vm-performance-is-a-threat-to-the-iphone/feed/</wfw:commentRss>
		<slash:comments>90</slash:comments>
		</item>
		<item>
		<title>Maven artifacts need to be more discoverable</title>
		<link>http://www.javarants.com/2010/05/16/maven-artifacts-need-to-be-self-discoverable/</link>
		<comments>http://www.javarants.com/2010/05/16/maven-artifacts-need-to-be-self-discoverable/#comments</comments>
		<pubDate>Mon, 17 May 2010 01:04:17 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1302</guid>
		<description><![CDATA[The laundry list of repositories that are filling the POM in Maven projects has to go. The ideal of having a central store of all artifacts is clearly dead and we have to move on. My proposal is two fold. &#8230; <a href="http://www.javarants.com/2010/05/16/maven-artifacts-need-to-be-self-discoverable/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The laundry list of repositories that are filling the POM in Maven projects has to go.  The ideal of having a central store of all artifacts is clearly dead and we have to move on.  My proposal is two fold.  First, the repository to end all repositories that doesn&#8217;t actually store the files but simply redirects to a known good location for the group id / artifact id / version combination.  The second is that we create an ad hoc standard for artifact discovery based on the group id.  For example, if the group id is com.sampullara.cli-parser then you should be able to find a repository that stores all artifacts at <a href="http://cli-parser.sampullara.com/repository/">http://cli-parser.sampullara.com/repository/</a>.  Perhaps we could even put some sort of discovery file at the root to find them.  This would allow anyone to distribute Maven artifacts to developers without having to publish to any central location.  It would also drastically reduce the amount of repository cruft that is creeping into so many of the POM files I have seen recently.  Further, it would make it really easy for github, googlecode, apache, etc to help their developers automatically publish with just the right naming conventions in place.</p>
<p>Come to think of it, maybe the whole thing is a little suspect.  Maybe we should have been using URLs the entire time.  How much value are we getting out of the layer of indirection?  This is intended to be a discussion&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/05/16/maven-artifacts-need-to-be-self-discoverable/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<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 &#8230; <a href="http://www.javarants.com/2008/12/27/using-jax-rs-with-protocol-buffers-for-high-performance-rest-apis/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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>18</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. <a href="http://www.javarants.com/2008/12/25/using-jax-rs-jersey-to-build-a-jpajaxb-backed-json-rest-api/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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>&#8216;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. &#8230; <a href="http://www.javarants.com/2008/05/19/better-javadoc-results-using-searchmonkey/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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>7</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 &#8230; <a href="http://www.javarants.com/2008/03/15/jpa-20-with-criteria/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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>4</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 &#8230; <a href="http://www.javarants.com/2007/10/14/generate-jpa-or-gorm-classes-from-your-database-for-java-and-grails/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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>
	</channel>
</rss>
