<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
   <channel>
      <title>Javarants</title>
      <description>Pipes Output</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=dth0BVnE2xG19PBwrscPhQ</link>
      <pubDate>Tue, 06 Jan 2009 06:42:57 -0800</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <geo:lat>37.353741</geo:lat><geo:long>-122.087172</geo:long><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://www.javarants.com/rss.xml" type="application/rss+xml" /><item>
         <title>Delicious/spullara on 01/05/2009</title>
         <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://esquifit.blogspot.com/2008/12/yql-and-greasmonkey.html'&gt;betrachtungen: YQL and Greasmonkey&lt;/a&gt;&lt;br&gt;YQL and Greasemonkey integration.&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://blogu.lu/mrm/2009/01/mrms-tv-guide/'&gt;mrm's TV Guide | blogu' lu' mrm&lt;/a&gt;&lt;br&gt;YQL being used for scraping TV listings. Truly turning the web into an API :)&lt;/p&gt;</description>
         <author>spullara</author>
         <guid isPermaLink="false">http://esquifit.blogspot.com/2008/12/yql-and-greasmonkey.html</guid>
         <pubDate>Mon, 05 Jan 2009 11:37:05 -0800</pubDate>
      </item>
      <item>
         <title>Delicious/spullara on 01/02/2009</title>
         <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://aws.typepad.com/aws/2009/01/bits-for-sale-amazon-s3-requester-payment-model.html'&gt;Amazon Web Services Blog: Bits For Sale - The New Amazon S3 Requester Pays Model&lt;/a&gt;&lt;br&gt;Seems like a reasonable way for Wikipedia and others to make money would be to put their downloads on S3 and charge a markup.&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://raphaeljs.com/'&gt;Raphaël—JavaScript Library&lt;/a&gt;&lt;br&gt;I am a terrible designer so I doubt I will ever need this but... wow thats cool!&lt;/p&gt;</description>
         <author>spullara</author>
         <guid isPermaLink="false">http://aws.typepad.com/aws/2009/01/bits-for-sale-amazon-s3-requester-payment-model.html</guid>
         <pubDate>Fri, 02 Jan 2009 17:06:28 -0800</pubDate>
      </item>
      <item>
         <title>Delicious/spullara on 01/01/2009</title>
         <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://randomfoo.net/blog/id/4218'&gt;random($foo): Online Tools for A New Small Business&lt;/a&gt;&lt;br&gt;Great survey of some small business tools.&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://developer.amazonwebservices.com/connect/thread.jspa?threadID=27622&amp;tstart=0'&gt;Amazon Web Services Developer Community : Announcing “Requester Pays” Option for ...&lt;/a&gt;&lt;br&gt;This is really cool for interesting datasets.&lt;/p&gt;</description>
         <author>spullara</author>
         <guid isPermaLink="false">http://randomfoo.net/blog/id/4218</guid>
         <pubDate>Thu, 01 Jan 2009 22:46:31 -0800</pubDate>
      </item>
      <item>
         <title>Delicious/spullara on 12/31/2008</title>
         <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://almaer.com/blog/not-just-social-history-actual-information-from-twitter'&gt;Not just social history, actual information from Twitter on Dion Almaer's Blog&lt;/a&gt;&lt;br&gt;Being able to post a tweet sounds like an interesting way to advertise my blog! :)&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://www.cloudera.com/blog/2008/12/31/whats-new-in-hadoop-core-019/'&gt;Cloudera Hadoop &amp; Big Data Blog » Blog Archive » What’s New in Hadoop Core 0.19&lt;/a&gt;&lt;br&gt;Thanks for the write up Cloudera! Looks like a lot of great changes have gone into 0.19.&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm'&gt;Architectural Styles and the Design of Network-based Software Architectures&lt;/a&gt;&lt;br&gt;Some light reading for the holiday.&lt;/p&gt;</description>
         <author>spullara</author>
         <guid isPermaLink="false">http://almaer.com/blog/not-just-social-history-actual-information-from-twitter</guid>
         <pubDate>Wed, 31 Dec 2008 13:52:06 -0800</pubDate>
      </item>
      <item>
         <title>Delicious/spullara on 12/30/2008</title>
         <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://www.jetbrains.com/mps/docs/tutorial.html'&gt;JetBrains :: Meta Programming System - Tutorial&lt;/a&gt;&lt;br&gt;I still think these guys are crazy, now 5 years later. The hello world for this thing is just outrageous.&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://blogs.smugmug.com/don/2008/12/23/great-things-afoot-in-the-mysql-community/'&gt;SmugBlog: Don MacAskill » Blog Archive » Great things afoot in the MySQL community&lt;/a&gt;&lt;br&gt;Great summary of the interesting things going on with MySQL.&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://java.sys-con.com/author/49'&gt;Sam Pullara @ JAVA DEVELOPER'S JOURNAL&lt;/a&gt;&lt;br&gt;Some great articles on WebLogic from 2002. It amuses me how many things that were in WebLogic are just now being codified into standards by the JSR process.&lt;/p&gt;</description>
         <author>spullara</author>
         <guid isPermaLink="false">http://www.jetbrains.com/mps/docs/tutorial.html</guid>
         <pubDate>Tue, 30 Dec 2008 20:56:03 -0800</pubDate>
      </item>
      <item>
         <title>Delicious/spullara on 12/29/2008</title>
         <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://www.devx.com/webdev/Article/40432'&gt;An Introduction to the Yahoo! Query Language Platform&lt;/a&gt;&lt;br&gt;In-depth article on using YQL.&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://www.cisa.informatics.ed.ac.uk/OK/drupal/home'&gt;OpenKnowledge&lt;/a&gt;&lt;br&gt;The write up I read on this was terrible but it looks interesting enough to investigate further.&lt;/p&gt;</description>
         <author>spullara</author>
         <guid isPermaLink="false">http://www.devx.com/webdev/Article/40432</guid>
         <pubDate>Mon, 29 Dec 2008 11:03:24 -0800</pubDate>
      </item>
      <item>
         <title>Delicious/spullara on 12/28/2008</title>
         <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href='http://blog.maxindelicato.com/2008/12/how-to-organize-a-database-tables-keys-for-scalability.html'&gt;blog.maxindelicato.com: How to Organize a Database Table’s Keys for Scalability&lt;/a&gt;&lt;br&gt;The obvious thing he misses here is that if you declare a huge number of virtual shards up front you never have to change the shard id of a record.&lt;/p&gt;</description>
         <author>spullara</author>
         <guid isPermaLink="false">http://blog.maxindelicato.com/2008/12/how-to-organize-a-database-tables-keys-for-scalability.html</guid>
         <pubDate>Sun, 28 Dec 2008 18:58:05 -0800</pubDate>
      </item>
      <item>
         <title>Using JAX-RS with Protocol Buffers for high-performance REST APIs</title>
         <link>http://feeds.feedburner.com/~r/javarants/~3/496759435/</link>
         <description>&lt;p&gt;One of the great things about the &lt;a rel="nofollow" target="_blank" href="http://jcp.org/aboutJava/communityprocess/final/jsr311/index.html"&gt;JAX-RS specification&lt;/a&gt; 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 &lt;a rel="nofollow" target="_blank" href="http://code.google.com/apis/protocolbuffers/docs/overview.html"&gt;Google Protocol Buffers&lt;/a&gt;. 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 &lt;a rel="nofollow" target="_blank" href="http://java.sun.com/developer/technicalArticles/xml/fastinfoset/"&gt;Fast Infoset&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://incubator.apache.org/thrift/"&gt;Thrift&lt;/a&gt;. Extending JAX-RS to support those protocols is nearly identical so all of the ideas I&amp;#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.&lt;/p&gt;
&lt;p&gt;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 &lt;a rel="nofollow" target="_blank" href="http://code.google.com/p/protobuf/"&gt;here&lt;/a&gt;. 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 &lt;a rel="nofollow" target="_blank" href="https://jersey.dev.java.net/"&gt;jersey-1.0.1&lt;/a&gt;) though I don&amp;#8217;t expect the API to change very much going forward. Once you have &lt;em&gt;protoc&lt;/em&gt; in your path you are ready to create your first JAX-RS / protobuf project.&lt;/p&gt;
&lt;p&gt;The dependencies you will need to create the application are actually quite small. I use &lt;a rel="nofollow" target="_blank" href="http://maven.apache.org/"&gt;Maven&lt;/a&gt; (and &lt;a rel="nofollow" target="_blank" href="http://www.jetbrains.com/idea/download/"&gt;IntelliJ 8.0&lt;/a&gt;) to do my development so that is how I&amp;#8217;ll describe what you need. For running the application you&amp;#8217;ll need these installed:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;com.sun.jersey&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;jersey-server&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;1.0.1&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;com.sun.grizzly&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;grizzly-servlet-webserver&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;1.8.6.3&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;com.google.protobuf&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;protobuf-java&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;2.0.3&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Then to execute the tests that we will create to verify that things are working as expected you&amp;#8217;ll need two additional test-time only dependencies:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;com.sun.jersey&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;jersey-client&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;1.0.1&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;scope&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;test&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;scope&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;junit&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;junit&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;4.5&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;scope&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;test&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;scope&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Not a huge set of dependencies on the surface but Maven does hide a lot of the complexity underneath &amp;#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&amp;#8217;ll just use the one from their &lt;a rel="nofollow" target="_blank" href="http://code.google.com/apis/protocolbuffers/docs/javatutorial.html"&gt;example&lt;/a&gt;, addressbook.proto:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(102,0,0);font-weight:bold;font-style:normal;"&gt;package&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; tutorial; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;option&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,102,102);font-weight:bold;font-style:normal;"&gt;java_package&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; = &lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"com.sampullara.jaxrsprotobuf.tutorial"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;option&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,102,102);font-weight:bold;font-style:normal;"&gt;java_outer_classname&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; = &lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"AddressBookProtos"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; &lt;/span&gt;&lt;span style="color:rgb(102,0,0);font-weight:bold;font-style:normal;"&gt;message&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; Person { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;required&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;string&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; name = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;1&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;required&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;int32&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; id = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;2&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;optional&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;string&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; email = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;3&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; &lt;/span&gt;&lt;span style="color:rgb(102,0,0);font-weight:bold;font-style:normal;"&gt;enum&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; PhoneType { MOBILE = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;0&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; HOME = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;1&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; WORK = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;2&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; } &lt;/span&gt;&lt;span style="color:rgb(102,0,0);font-weight:bold;font-style:normal;"&gt;message&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; PhoneNumber { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;required&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;string&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; number = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;1&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;optional&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; PhoneType type = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;2&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; [&lt;/span&gt;&lt;span style="color:rgb(0,102,102);font-weight:bold;font-style:normal;"&gt;default&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; = HOME]; } &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;repeated&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; PhoneNumber phone = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;4&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;;
} &lt;/span&gt;&lt;span style="color:rgb(102,0,0);font-weight:bold;font-style:normal;"&gt;message&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; AddressBook { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;repeated&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; Person person = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;1&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;;
}
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;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 &lt;a rel="nofollow" target="_blank" href="https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/ext/package-summary.html"&gt;extension SPI&lt;/a&gt; of JAX-RS. This service will have two methods, a GET method for returning a new instance of a &lt;em&gt;Person&lt;/em&gt; 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:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;package&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; com.sampullara.jaxrsprotobuf.tutorial; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;import&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; javax.ws.rs.*; &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Path&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"/person"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;)
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; AddressBookService { &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@GET&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Produces&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"application/x-protobuf"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; AddressBookProtos.Person getPerson() { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;return&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; AddressBookProtos.Person.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;newBuilder&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;() .setId(&lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;1&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) .setName(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"Sam"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) .setEmail(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"sam@sampullara.com"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) .addPhone(AddressBookProtos.Person.PhoneNumber.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;newBuilder&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;() .setNumber(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"415-555-1212"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) .setType(AddressBookProtos.Person.PhoneType.&lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:italic;"&gt;MOBILE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) .build()) .build(); } &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@POST&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Consumes&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"application/x-protobuf"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Produces&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"application/x-protobuf"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; AddressBookProtos.Person reflect(AddressBookProtos.Person person) { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;return&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; person; }
}
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;For each of these methods we&amp;#8217;ve restricted them to either consuming or producing content of type &lt;em&gt;application/x-protobuf&lt;/em&gt;. 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:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Provider&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Consumes&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"application/x-protobuf"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;static&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; ProtobufMessageBodyReader &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;implements&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; MessageBodyReader&amp;lt;Message&amp;gt; { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;boolean&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; isReadable(Class&amp;lt;?&amp;gt; type, Type genericType, Annotation[] annotations, MediaType mediaType) { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;return&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; Message.&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.isAssignableFrom(type); } &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; Message readFrom(Class&amp;lt;Message&amp;gt; type, Type genericType, Annotation[] annotations,&lt;/span&gt;
&lt;span style="color:rgb(0,0,128);font-weight:normal;font-style:normal;"&gt; MediaType mediaType, MultivaluedMap&amp;lt;String, String&amp;gt; httpHeaders, &lt;/span&gt;
&lt;span style="color:rgb(0,0,128);font-weight:normal;font-style:normal;"&gt; InputStream entityStream) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;throws&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; IOException, WebApplicationException { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;try&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; { Method newBuilder = type.getMethod(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"newBuilder"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); GeneratedMessage.Builder builder = (GeneratedMessage.Builder) newBuilder.invoke(type); &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;return&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; builder.mergeFrom(entityStream).build(); } &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;catch&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; (Exception e) { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;throw&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;new&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; WebApplicationException(e); } } }
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;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 &lt;em&gt;Application&lt;/em&gt;. You&amp;#8217;ll see in our Main method later we use the former strategy. You&amp;#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&amp;#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.&lt;/p&gt;
&lt;p&gt;The writer is a bit more complicated because in addition to the &lt;em&gt;isWritable&lt;/em&gt; and &lt;em&gt;writeTo&lt;/em&gt; 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 &lt;em&gt;getSize&lt;/em&gt; and temporarily store the result with a weak map. In the future I&amp;#8217;d like to see streaming better supported. Here is how I implemented the writer:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Provider&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Produces&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"application/x-protobuf"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;static&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; ProtobufMessageBodyWriter &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;implements&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; MessageBodyWriter&amp;lt;Message&amp;gt; { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;boolean&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; isWriteable(Class&amp;lt;?&amp;gt; type, Type genericType, Annotation[] annotations, MediaType mediaType) { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;return&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; Message.&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.isAssignableFrom(type); } &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;private&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; Map&amp;lt;Object, &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;byte&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;[]&amp;gt; &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;buffer&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; = &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;new&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; WeakHashMap&amp;lt;Object, &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;byte&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;[]&amp;gt;(); &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;long&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; getSize(Message m, Class&amp;lt;?&amp;gt; type, Type genericType, Annotation[] annotations, MediaType mediaType) { ByteArrayOutputStream baos = &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;new&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; ByteArrayOutputStream(); &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;try&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; { m.writeTo(baos); } &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;catch&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; (IOException e) { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;return&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; -&lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;1&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; } &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;byte&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;[] bytes = baos.toByteArray(); &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;buffer&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.put(m, bytes); &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;return&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; bytes.&lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;length&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; } &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;void&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; writeTo(Message m, Class type, Type genericType, Annotation[] annotations, &lt;/span&gt;
&lt;span style="color:rgb(0,0,128);font-weight:normal;font-style:normal;"&gt; MediaType mediaType, MultivaluedMap httpHeaders,&lt;/span&gt;
&lt;span style="color:rgb(0,0,128);font-weight:normal;font-style:normal;"&gt; OutputStream entityStream) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;throws&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; IOException, WebApplicationException { entityStream.write(&lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;buffer&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.remove(m)); } }
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I&amp;#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:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;plugin&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;maven-antrun-plugin&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;executions&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;execution&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;id&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;generate-sources&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;id&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;phase&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;generate-sources&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;phase&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;configuration&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;tasks&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;mkdir&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,255);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;dir=&lt;/span&gt;&lt;span style="color:rgb(0,128,0);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;&amp;apos;target/generated-sources&amp;apos;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt; /&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;exec&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,255);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;executable=&lt;/span&gt;&lt;span style="color:rgb(0,128,0);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;&amp;apos;protoc&amp;apos;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;arg&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,255);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;value=&lt;/span&gt;&lt;span style="color:rgb(0,128,0);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;&amp;apos;--java_out=target/generated-sources&amp;apos;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt; /&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;arg&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,255);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;value=&lt;/span&gt;&lt;span style="color:rgb(0,128,0);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;&amp;apos;src/main/resources/addressbook.proto&amp;apos;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt; /&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;exec&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;tasks&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;sourceRoot&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;target/generated-sources&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;sourceRoot&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;configuration&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;goals&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;goal&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:bold;font-style:normal;"&gt;run&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;goal&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;goals&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;execution&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;executions&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:rgb(0,0,128);background-color:rgb(239,239,239);font-weight:bold;font-style:normal;"&gt;plugin&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(239,239,239);font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;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 &lt;a rel="nofollow" target="_blank" href="https://grizzly.dev.java.net/"&gt;Grizzly&lt;/a&gt; container:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; Main { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;static&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;final&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; URI &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:italic;"&gt;BASE_URI&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; = UriBuilder.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;fromUri&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"http://localhost/"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;).port(&lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;9998&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;).build(); &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;static&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;void&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; main(String[] args) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;throws&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; IOException { System.&lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:italic;"&gt;out&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.println(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"Starting grizzly..."&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); URI uri = &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:italic;"&gt;BASE_URI&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; SelectorThread threadSelector = &lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;createServer&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(uri); System.&lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:italic;"&gt;out&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.println(String.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;format&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"Try out %sperson&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;&amp;#92;n&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;Hit enter to stop it..."&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, uri)); System.&lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:italic;"&gt;in&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(246,235,188);font-weight:normal;font-style:normal;"&gt;read&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(); threadSelector.stopEndpoint(); } &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;static&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; SelectorThread createServer(URI uri) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;throws&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; IOException { Map&amp;lt;String, String&amp;gt; initParams = &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;new&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; HashMap&amp;lt;String, String&amp;gt;(); initParams.put(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"com.sun.jersey.config.property.packages"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, &lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"com.sampullara"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;return&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; GrizzlyWebContainerFactory.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;create&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(uri, initParams); }
}
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;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 &lt;em&gt;setUp&lt;/em&gt;() and &lt;em&gt;tearDown&lt;/em&gt;():&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;private&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; SelectorThread &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;threadSelector&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;private&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; WebResource &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;r&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;; &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Override&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;protected&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;void&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; setUp() &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;throws&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; Exception { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;super&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.setUp(); &lt;/span&gt;&lt;span style="color:rgb(128,128,128);font-weight:normal;font-style:italic;"&gt;//start the Grizzly web container and create the client&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;threadSelector&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; = Main.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;createServer&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(Main.&lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:italic;"&gt;BASE_URI&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); ClientConfig cc = &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;new&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; DefaultClientConfig(); cc.getClasses().add(ProtobufProviders.ProtobufMessageBodyReader.&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); cc.getClasses().add(ProtobufProviders.ProtobufMessageBodyWriter.&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); Client c = Client.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;create&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(cc); &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;r&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; = c.resource(Main.&lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:italic;"&gt;BASE_URI&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); } &lt;/span&gt;&lt;span style="color:rgb(128,128,0);font-weight:normal;font-style:normal;"&gt;@Override&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;protected&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;void&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; tearDown() &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;throws&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; Exception { &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;super&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.tearDown(); &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;threadSelector&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.stopEndpoint(); } &lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The client doesn&amp;#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&amp;#8217;t have to worry about mismatched configurations. The first tests we will run will be using the Jersey client:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;void&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; testUsingJerseyClient() { WebResource wr = &lt;/span&gt;&lt;span style="color:rgb(102,14,122);font-weight:bold;font-style:normal;"&gt;r&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.path(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"person"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); AddressBookProtos.Person p = wr.get(AddressBookProtos.Person.&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); &lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;assertEquals&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"Sam"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, p.getName()); AddressBookProtos.Person p2 = wr.type(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"application/x-protobuf"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;).post(AddressBookProtos.Person.&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;class&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, p); &lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;assertEquals&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(p, p2); }
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;public&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;void&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; testUsingURLConnection() &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;throws&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; IOException { AddressBookProtos.Person person; { URL url = &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;new&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; URL(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"http://localhost:9998/person"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); URLConnection urlc = url.openConnection(); urlc.setDoInput(&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;true&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); urlc.setRequestProperty(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"Accept"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, &lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"application/x-protobuf"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); person = AddressBookProtos.Person.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;newBuilder&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;().mergeFrom(urlc.getInputStream()).build(); &lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;assertEquals&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"Sam"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, person.getName()); } { URL url = &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;new&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; URL(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"http://localhost:9998/person"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); HttpURLConnection urlc = (HttpURLConnection) url.openConnection(); urlc.setDoInput(&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;true&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); urlc.setDoOutput(&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;true&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); urlc.setRequestMethod(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"POST"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); urlc.setRequestProperty(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"Accept"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, &lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"application/x-protobuf"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); urlc.setRequestProperty(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"Content-Type"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, &lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"application/x-protobuf"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;); person.writeTo(urlc.getOutputStream()); AddressBookProtos.Person person2 = AddressBookProtos.Person.&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;newBuilder&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;().mergeFrom(urlc.getInputStream()).build(); &lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:italic;"&gt;assertEquals&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(person, person2); } }
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;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&amp;#8217;t we try this with some Python 2.5 code:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;import&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;urllib&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;import&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; addressbook_pb2 f = &lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;urllib&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;.urlopen(&lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;"http://localhost:9998/person"&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;)
person = addressbook_pb2.Person()
&lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(246,235,188);font-weight:normal;font-style:normal;"&gt;person.ParseFromString&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(f.read())
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;print&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,0);background-color:rgb(246,235,188);font-weight:normal;font-style:normal;"&gt;person.name&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Works great and outputs &amp;#8220;Sam&amp;#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.&lt;/p&gt;
&lt;p&gt;For those that just want to open up the final product and see how it all works, here is a &lt;a rel="nofollow" target="_blank" href="http://buildandtest.com/files/jaxrs-protobuf.zip"&gt;link to download it&lt;/a&gt;. You&amp;#8217;ll also note that I actually use &lt;a rel="nofollow" target="_blank" href="http://code.google.com/p/graven/"&gt;graven&lt;/a&gt; under the covers to do my builds as Maven&amp;#8217;s XML is a little too verbose for me.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/javarants?a=8stnO"&gt;&lt;img src="http://feeds.feedburner.com/~f/javarants?i=8stnO" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/javarants?a=Jur1O"&gt;&lt;img src="http://feeds.feedburner.com/~f/javarants?i=Jur1O" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/javarants/~4/496759435" height="1" width="1"/&gt;</description>
         <author>sam</author>
         <guid isPermaLink="false">http://www.javarants.com/?p=955</guid>
         <pubDate>Sat, 27 Dec 2008 19:55:59 -0800</pubDate>
      <feedburner:origLink>http://www.javarants.com/2008/12/27/using-jax-rs-with-protocol-buffers-for-high-performance-rest-apis/</feedburner:origLink></item>
      <item>
         <title>Build your own mail analyzer for Mac Mail.app</title>
         <link>http://feeds.feedburner.com/~r/javarants/~3/496068549/</link>
         <description>&lt;p&gt;You&amp;#8217;ve probably read about things like Xoopit and Xobni for analyzing both online mail and your outlook mail. As it turns out, Apple has done something great in this regard that I think has been mostly overlooked. Mail.app stores all of the meta-data for you email in a file called &lt;i&gt;~/Library/Mail/Envelope Index&lt;/i&gt;. You might wonder what the format of this file is&amp;#8230; well it is a SQLite3 database. The contents are pretty easy to see, go to the terminal and type:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;macpro:~ sam$ sqlite3 ~/Library/Mail/Envelope&amp;#92; Index&lt;br /&gt;
SQLite version 3.6.3&lt;br /&gt;
Enter ".help" for instructions&lt;br /&gt;
Enter SQL statements terminated with a ";"&lt;br /&gt;
sqlite&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Everything about your mailboxes is stored within this database and the structure of the database is normalized so its very easy to navigate. The tables of most interest for mail analysis are:&lt;/p&gt;
&lt;pre&gt;
sqlite&amp;gt; .tables
&lt;strong&gt;addresses&lt;/strong&gt; &lt;strong&gt;mailboxes&lt;/strong&gt; todo_notes
alarms &lt;strong&gt;messages&lt;/strong&gt; todos
associations properties todos_deleted_log
&lt;strong&gt;attachments&lt;/strong&gt; &lt;strong&gt;recipients&lt;/strong&gt; todos_server_snapshot
calendars &lt;strong&gt;subjects&lt;/strong&gt;
feeds &lt;strong&gt;threads&lt;/strong&gt;
&lt;/pre&gt;
&lt;p&gt;Fortunately, accessing a SQLite database is quite easy from just about any language that you decide to use. I&amp;#8217;m just going to do all the queries in straight sqlite3 rather than a language, but they could be embedded in your application. First things first, copy your &lt;em&gt;Envelope Index&lt;/em&gt; to another directory:&lt;/p&gt;
&lt;pre&gt;macpro:tmp sam$ cp ~/Library/Mail/Envelope&amp;#92; Index .&lt;/pre&gt;
&lt;p&gt;Now you can use that database without worrying about messing up the locking or corrupting data while Mail.app is using it. Since we might as well do an example that is interesting rather than merely educational, how about we answer the question: &amp;#8220;Who are my coworkers with whom that I collaborated?&amp;#8221;. This is going to be a multi-query process to extract the information &amp;#8212; there may be more efficient ways to do it &amp;#8212; but think of this as instructive rather than prescriptive. First I need to limit the query to only those mailboxes which contain work email:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;DROP&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;TABLE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkermailboxes;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;CREATE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;TABLE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkermailboxes(id);
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;CREATE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; INDEX coworkermailboxes_index &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;ON&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkermailboxes(id);
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;INSERT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;INTO&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkermailboxes &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; rowid &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; mailboxes
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;WHERE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
url &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;like&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;&amp;apos;imap://samp@snv-webmail.corp.yahoo.com/%&amp;apos;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;OR&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
url &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;like&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,128,0);font-weight:bold;font-style:normal;"&gt;&amp;apos;imap://sam@mail.sampullara.com/Yahoo%20Inc%20Archive&amp;apos;&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;That gives us a table with several mailboxes that I have in Mail.app including Sent Messages. I would peruse the list of mailboxes to ensure that you are grabbing all the correct information. For me I had to also search my archives. Now I am going to take a series of steps to get to the final out put by iteratively processing successive tables of information. The first table, is a list of those people that you have both sent and received an email with directly (they were the sender and you were a receiver or you were the sender and they were the receiver):&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;DROP&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;TABLE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;CREATE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;TABLE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers(id);
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;CREATE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; INDEX coworkers_index &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;ON&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers(id);
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;INSERT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;INTO&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; a.rowid &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; addresses a, messages m, recipients r
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;WHERE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
m.sender = a.rowid &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
m.mailbox &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;IN&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; (&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; id &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkermailboxes) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
r.message_id = m.rowid &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; r.address_id = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;4&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;INTERSECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; a.rowid &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; addresses a, messages m, recipients r
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;WHERE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
m.sender = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;4&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
m.mailbox &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;IN&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; (&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; id &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkermailboxes) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
r.message_id = m.rowid &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; r.address_id = a.rowid
;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note I have directly inserted my addresses rowid into this query for the sender on the one hand and the receiver on the other. The next step will be to count the actual number of emails you have received from each of those on the list:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;DROP&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;TABLE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers2;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;CREATE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;TABLE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers2(id, recv);
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;CREATE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; INDEX coworkers2_index &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;ON&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers2(id);
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; "Get the received mail";
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;INSERT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;INTO&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers2 &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; w.id, &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;COUNT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(*) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; messages m, recipients r, coworkers w
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;WHERE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; m.sender = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;4&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
m.mailbox &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;IN&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; (&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; id &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkermailboxes) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
r.message_id = m.rowid &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; r.address_id = w.id
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;GROUP&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;BY&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; w.id &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;ORDER&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;BY&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;COUNT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(*)
;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Finally, we count the number of sent emails and also derive a ratio of sent/received so we can judge how collaborative the exchanges have been:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;DROP&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;TABLE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers3;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;CREATE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;TABLE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers3(id, sent &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;float&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, recv &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;float&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;, ratio &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;float&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;);
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;CREATE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; INDEX coworkers3_index &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;ON&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers3(id);
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; "Get the sent mail";
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;INSERT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;INTO&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkers3 &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; w.id, &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;COUNT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(*), w.recv, &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;COUNT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(*)*&lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;1.0&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;/w.recv &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; messages m, recipients r, coworkers2 w
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;WHERE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
m.sender = w.id &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
m.mailbox &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;IN&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; (&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; id &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; coworkermailboxes) &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
r.message_id = m.rowid &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; r.address_id = &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;4&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;GROUP&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;BY&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; w.id &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;ORDER&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;BY&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;COUNT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;(*)
;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You will now have a table named &lt;em&gt;coworkers3&lt;/em&gt; that can be mined for information about your level of correspondence with them. For example, here is way to find relatively equal sends and receives:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; a.comment &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; addresses a, coworkers3 w
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;WHERE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
a.rowid = w.id &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
ratio &amp;gt;= &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;.5&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
ratio &amp;lt;=&lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;2&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
sent &amp;gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;10&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;ORDER&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;BY&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; sent
LIMIT &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;20&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;When I do this I see the people that either I use to find information or that use me to find information. Every interaction is usually a request and then a response. On the other hand, this query will find those that typically made announcements out to the groups that I also worked with:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;SELECT&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; a.comment &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;FROM&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; addresses a, coworkers3 w
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;WHERE&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
a.rowid = w.id &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
ratio &amp;lt;= &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;1&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;AND&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
sent &amp;gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;10&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;
&lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;ORDER&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; &lt;/span&gt;&lt;span style="color:rgb(0,0,128);font-weight:bold;font-style:normal;"&gt;BY&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt; ratio
LIMIT &lt;/span&gt;&lt;span style="color:rgb(0,0,255);font-weight:normal;font-style:normal;"&gt;20&lt;/span&gt;&lt;span style="color:rgb(0,0,0);font-weight:normal;font-style:normal;"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And so on. Adding more filters on top of this you could easily derive your team at work for a particular time period and other insights. With the wealth of information contained in this meta-data store you could figure out all kinds of things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Who sent you an email that you didn&amp;#8217;t reply to yet?&lt;/li&gt;
&lt;li&gt;Who do you respond to the most quickly?&lt;/li&gt;
&lt;li&gt;Who responds to you most quickly?&lt;/li&gt;
&lt;li&gt;What are you and your coworkers approximate working hours?&lt;/li&gt;
&lt;li&gt;What groups of CCs could be made into aliases?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There really is no limit to how far the analysis could go. Ideally, it would be possible to setup a dashboard in Mail.app that let you cut and slice the data in a far more precise way than smart folders currently allow today. Maybe they should come out with super-sql-smart folders!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/javarants?a=smmxO"&gt;&lt;img src="http://feeds.feedburner.com/~f/javarants?i=smmxO" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/javarants?a=lJe3O"&gt;&lt;img src="http://feeds.feedburner.com/~f/javarants?i=lJe3O" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/javarants/~4/496068549" height="1" width="1"/&gt;</description>
         <author>sam</author>
         <guid isPermaLink="false">http://www.javarants.com/?p=943</guid>
         <pubDate>Fri, 26 Dec 2008 19:46:49 -0800</pubDate>
      <feedburner:origLink>http://www.javarants.com/2008/12/26/build-your-own-mail-analyzer-for-mac-mailapp/</feedburner:origLink></item>
      <item>
         <title>Using JAX-RS (Jersey) to build a JPA/JAXB-backed JSON REST API</title>
         <link>http://feeds.feedburner.com/~r/javarants/~3/495272071/</link>
         <description>&lt;p&gt;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&amp;#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.&lt;/p&gt;
&lt;p&gt;I&amp;#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 &lt;a rel="nofollow" target="_blank" href="http://wiki.jruby.org/wiki/JRuby_on_Rails"&gt;JRuby on Rails&lt;/a&gt;, to &lt;a rel="nofollow" target="_blank" href="http://grails.org/"&gt;Grails&lt;/a&gt;, to &lt;a rel="nofollow" target="_blank" href="http://seamframework.org/"&gt;Seam&lt;/a&gt; and even just writing everything myself. Ultimately, I believe in the &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Don't_repeat_yourself"&gt;DRY&lt;/a&gt; principle (like Rails), though I don&amp;#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&amp;#8217;s data object model from it.&lt;/p&gt;
&lt;p&gt;So what are my acceptance criteria for this über-framework?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Great object-relational mapping tool that works well with MySQL + PostgreSQL&lt;/li&gt;
&lt;li&gt;Excellent support for consuming and producing XML and JSON that integrates with the well with the data objects that the ORM tool uses&lt;/li&gt;
&lt;li&gt;Supports writing MVC applications naturally&lt;/li&gt;
&lt;li&gt;Support for building REST APIs with arbitrary URL mapping to service parameters&lt;/li&gt;
&lt;li&gt;High straight-line performance with the ability to scale up servers&lt;/li&gt;
&lt;li&gt;Great defaults that make configuration mostly unnecessary with simple deployment&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://www.jetbrains.com/idea/"&gt;State-of-the-art IDE support&lt;/a&gt;. I don&amp;#8217;t like to type anymore nor memorize APIs.&lt;/li&gt;
&lt;li&gt;Suitable for quick prototyping and production applications&lt;/li&gt;
&lt;li&gt;Support for templating views of any output type (HTML, XML, etc)&lt;/li&gt;
&lt;li&gt;Easy to unit and integration test&lt;/li&gt;
&lt;li&gt;Open source&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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. &lt;a rel="nofollow" target="_blank" href="http://jcp.org/en/jsr/detail?id=311"&gt;JSR-311&lt;/a&gt; was stated to develop an API for providing support for &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;RESTful&lt;/a&gt; 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 &lt;a rel="nofollow" target="_blank" href="http://www.jcp.org/en/jsr/detail?id=220"&gt;JPA&lt;/a&gt; (my favorite ORM), support for both XML and JSON natively, and except in unusual circumstances very DRY.&lt;/p&gt;
&lt;p&gt;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&amp;#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 &lt;a rel="nofollow" target="_blank" href="https://grizzly.dev.java.net/"&gt;Grizzly&lt;/a&gt;, heavier ones like &lt;a rel="nofollow" target="_blank" href="http://tomcat.apache.org/"&gt;Tomcat&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="https://glassfish.dev.java.net/"&gt;Glassfish&lt;/a&gt;, and the REST APIs it creates can even be directly tested wi