<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kiji Community</title>
	<atom:link href="http://www.kiji.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kiji.org</link>
	<description>Build Real-Time Scalable Data Applications on Apache HBase</description>
	<lastBuildDate>Tue, 21 May 2013 01:15:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Revealing KijiREST: Resources</title>
		<link>http://www.kiji.org/2013/05/20/revealing-kijirest-resources/</link>
		<comments>http://www.kiji.org/2013/05/20/revealing-kijirest-resources/#comments</comments>
		<pubDate>Tue, 21 May 2013 01:00:07 +0000</pubDate>
		<dc:creator>Shashir Reddy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[kiji-rest]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[rpc]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1287</guid>
		<description><![CDATA[The KijiREST project emerged from growing interest in building a REST interface for Kiji. This blog is the first in a series explaining the usage of KijiREST v0.1.0 (included in Albacore BentoBox v1.0.4). Introduction REST APIs allow client applications to interact with server applications over HTTP by issuing the four actions GET, POST, PUT and...  <a href="http://www.kiji.org/2013/05/20/revealing-kijirest-resources/" class="more-link" title="Read Revealing KijiREST: Resources">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead"><em>The KijiREST project emerged from growing interest in building a REST interface for <a href="http://www.kiji.org/" title="Kiji">Kiji</a>. This blog is the first in a series explaining the usage of KijiREST v0.1.0 (included in <a href="http://www.kiji.org/announcing-the-albacore-bentobox-v1.0.4/" title="Albacore">Albacore BentoBox v1.0.4</a>).</em></p>
<h3>Introduction</h3>
<p><a href="http://en.wikipedia.org/wiki/REST" title="REST">REST</a> APIs allow client applications to interact with server applications over HTTP by issuing the four actions GET, POST, PUT and DELETE, which operate on server-side “resources.” In this post, we will introduce the basic KijiREST resources and their identifiers.</p>
<p>Every REST request is parametrized by a resource path that uniquely identifies a server-side resource. Other optional parameters relevant to the action are specified in the query and body sections of the request. The following call is an example row GET:</p>
<p><code>GET /v1/instances/dev_instance/tables/users/rows/c51ce410c124a10e0db5e4b97fc2af39[?...]</code></p>
<h3>Entry-point</h3>
<p>The KijiREST API version is placed at the root of the resource path. Mandatorily prefixing the resource path with the version in this manner results in graceful upgrades (see <a href="https://blog.apigee.com/detail/restful_api_design" title="Apigee's RESTful API Design">Apigee’s RESTful API Design</a> and <a href="http://www.lexicalscope.com/blog/2012/03/12/how-are-rest-apis-versioned/" title="Lexical Scope's How are REST APIs versioned?">Lexical Scope’s How are REST APIs versioned?</a> for case studies).</p>
<p><code>/v1/[...]</code></p>
<p>Every KijiREST service is associated with a single Kiji cluster and the cluster may be considered the “root” resource (after the REST API version, of course). The Kiji cluster’s version (distinct from the KijiREST API version) is a conceivable endpoint within the cluster:</p>
<p><code>/v1/version</code></p>
<h3>Instances</h3>
<p>A Kiji cluster contains Kiji instances. In order to avoid name clashes with other direct child resources of the Kiji cluster resource (e.g. <code>version</code>), all instances are grouped into a sub-collection named <code>instances</code> &#8212; this serves as a namespace for all instances on this cluster.</p>
<p><code>/v1/instances/</code></p>
<p><code>/v1/instances/&lt;instance&gt;</code></p>
<h3>Tables</h3>
<p>Every instance contains a subcollection named <code>tables</code> &#8212; this serves as a namespace for all the tables in this instance.</p>
<p><code>/v1/instances/&lt;instance&gt;/tables/</code></p>
<p><code>/v1/instances/&lt;instance&gt;/tables/&lt;table&gt;</code></p>
<h3>Rows</h3>
<p>Every table contains a subcollection named <code>rows</code>. Each <code>&lt;row&gt;</code> is identified by the ASCII encoding of its hexadecimal entity-id. Rows are the deepest identifiable resources.</p>
<p><code>/v1/instances/&lt;instance&gt;/tables/&lt;table&gt;/rows/</code></p>
<p><code>/v1/instances/&lt;instance&gt;/tables/&lt;table&gt;/rows/&lt;row&gt;</code></p>
<p>Instead of the hexadecimal entity-id, only the formatted entity-id for a row is available to provide advanced query features which accommodate resource identification &#8212; these concepts will be explained in greater detail in future posts. </p>
<p><em><strong>Observation.</strong> The collections </em><code>instances</code><em>, </em><code>tables</code><em>, and </em><code>rows</code><em> are all “homogeneous” sets in that they each only contain one respective resource type.</em></p>
<h3>The filesystem directory tree analogy</h3>
<p>The above scheme induces a simple directory tree analogy where directories represent collections of resources.</p>
<p>For example, consider a cluster where there are two instances named dev_instance and prod_instance. The prod_instance contains two tables named customers and songs. This hierarchy is best described in a diagram.</p>
<a href="http://static.kiji.org/wp-content/uploads/2013/06/kiji-rest-hierarchy.png"><img src="http://static.kiji.org/wp-content/uploads/2013/06/kiji-rest-hierarchy.png" alt="kiji-rest-hierarchy" class="alignnone size-full wp-image-1308" /></a>
<h3>Caveats</h3>
<p>Though they serve the similar purpose of identifying Kiji resources, KijiURIs and KijiREST resource paths must to be distinguished. Compare the following KijiURI and the KijiREST resource path.</p>
<p>KijiURI: <code>kiji://.env/prod/customers</code></p>
<p>REST resource path: <code>/v1/instances/prod/tables/customers/rows/[...]</code></p>
<p>The KijiURI can identify the Kiji cluster, but the KijiREST resource path can’t. The KijiREST resource path can identify a row within a table, but the KijiURI can’t. Moreover, the KijiREST resource path has explicit boxing of instances, tables, and rows in order to leave room for additional cluster-level, instance-level, table-level endpoints in the future.</p>
<h3>Finally</h3>
<p>Reasonably designing the REST identifiers allow clients to intuitively conceive server-side resources. Stay tuned for upcoming articles on KijiREST usage patterns.</p>
<h3>Resources</h3>
<p><a href="https://blog.apigee.com/detail/restful_api_design">https://blog.apigee.com/detail/restful_api_design</a></p>
<p><a href="https://restful-api-design.readthedocs.org/en/latest/resources.html">https://restful-api-design.readthedocs.org/en/latest/resources.html</a></p>
<p><a href="http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html">http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html </a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/2013/05/20/revealing-kijirest-resources/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing the “Albacore” BentoBox v1.0.4</title>
		<link>http://www.kiji.org/announcing-the-albacore-bentobox-v1.0.4/</link>
		<comments>http://www.kiji.org/announcing-the-albacore-bentobox-v1.0.4/#comments</comments>
		<pubDate>Tue, 14 May 2013 17:27:07 +0000</pubDate>
		<dc:creator>Lee Sheng</dc:creator>
				<category><![CDATA[BentoBox]]></category>
		<category><![CDATA[Releases]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1272</guid>
		<description><![CDATA[Announcing the “Albacore” BentoBox v1.0.4 We are pleased to announce an updated version of the BentoBox SDK for Kiji. This system includes several upgraded components and will make it easier to deliver new releases of Kiji software to you as well. See the previous announcement here. Albacore v1.0.4 includes the following software: KijiSchema 1.0.3 KijiSchema...  <a href="http://www.kiji.org/announcing-the-albacore-bentobox-v1.0.4/" class="more-link" title="Read Announcing the “Albacore” BentoBox v1.0.4">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead">Announcing the “Albacore” BentoBox v1.0.4</p>
<p>We are pleased to announce an <a href="http://archive.kiji.org/tarballs/kiji-bento-albacore-1.0.4-release.tar.gz">updated version of the BentoBox SDK</a> for Kiji. This system includes several upgraded components and will make it easier to deliver new releases of Kiji software to you as well. See the previous announcement <a href="http://www.kiji.org/2013/04/09/announcing-the-albacore-bentobox/">here</a>.</p>
<p>Albacore v1.0.4 includes the following software:</p>
<ul>
<li>KijiSchema 1.0.3
<li>KijiSchema shell 1.0.0
<li>KijiMR 1.0.0-rc62
<li>KijiMR Library 1.0.0-rc61
<li>Kiji Hive Adapter 0.3.0 <strong>*UPDATED*</strong>
<li>KijiExpress 0.3.0 <strong>*UPDATED*</strong>
<li>KijiREST 0.1.0 <strong>*NEW*</strong>
<li>Example code: phonebook and music recommendation tutorials
</ul>
<p>This BentoBox is powered by Hadoop and HBase via CDH 4.1. It is built around the latest version of KijiSchema.</p>
<h3>New: KijiREST</h3>
<p>This version of the BentoBox is the first to contain KijiREST, a REST interface for interacting with KijiSchema.<br />
KijiREST is in the <tt>rest/</tt> directory of the BentoBox. Its README includes instructions on configuring and running a REST service.. </p>
<h3>Notable updates to Kiji Hive Adapter and KijiExpress</h3>
<p>A new release of Kiji Hive Adapter and KijiExpress have been provided.</p>
<ul>
<li>There is now a KijiExpress Shell. A Scala shell preloaded for KijiExpress can now be run with the command &#8220;<tt>express shell --local</tt>&#8221; or &#8220;<tt>express shell --hdfs</tt>&#8220;. Once a pipe is fully specified from input to output, it can be run with &#8220;pipe.run&#8221;.
<li>The Kiji Hive Adapter now allows the ability to read EntityId in Hive.  Thanks to Jeff Kolesky for the patch!
<li>Various additional bug fixes.
</ul>
<h3>Conclusions</h3>
<p>We’re excited about the momentum building behind the BentoBox. New components, improved software stability, and a smoother upgrade process will help enable more powerful big data applications to be built with the BentoBox SDK.</p>
<p>Ready to get started? <a href="http://www.kiji.org/getstarted/#Downloads">Download the BentoBox</a> today!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/announcing-the-albacore-bentobox-v1.0.4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing Albacore BentoBox v1.0.3</title>
		<link>http://www.kiji.org/announcing-the-albacore-bentobox-v1.0.3/</link>
		<comments>http://www.kiji.org/announcing-the-albacore-bentobox-v1.0.3/#comments</comments>
		<pubDate>Tue, 30 Apr 2013 23:28:29 +0000</pubDate>
		<dc:creator>Lee Sheng</dc:creator>
				<category><![CDATA[BentoBox]]></category>
		<category><![CDATA[Releases]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1247</guid>
		<description><![CDATA[Announcing the &#8220;Albacore&#8221; BentoBox v1.0.3 We are pleased to announce an updated version of the BentoBox SDK for Kiji. This system includes several upgraded components and will make it easier to deliver new releases of Kiji software to you as well. See the previous announcement here Albacore v1.0.3 includes the following software: KijiSchema 1.0.3 KijiSchema...  <a href="http://www.kiji.org/announcing-the-albacore-bentobox-v1.0.3/" class="more-link" title="Read Announcing Albacore BentoBox v1.0.3">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead">Announcing the &#8220;Albacore&#8221; BentoBox v1.0.3</p>
<p>We are pleased to announce an <a href="http://archive.kiji.org/tarballs/kiji-bento-albacore-1.0.3-release.tar.gz">updated version of the BentoBox SDK</a> for Kiji. This system includes several upgraded components and will make it easier to deliver new releases of Kiji software to you as well.  See the previous announcement <a href="http://www.kiji.org/2013/04/09/announcing-the-albacore-bentobox/">here</a></p>
<p>Albacore v1.0.3 includes the following software:</p>
<ul>
<li>KijiSchema 1.0.3</li>
<li>KijiSchema shell 1.0.0</li>
<li>KijiMR 1.0.0-rc62</li>
<li>KijiMR Library 1.0.0-rc61</li>
<li>Kiji Hive adapter 0.2.0</li>
<li>Kiji Express 0.2.0 <strong>*NEW*</strong></li>
<li>Example code: phonebook and music recommendation tutorials</li>
</ul>
<p>This BentoBox is powered by Hadoop and HBase via CDH 4.1. It is built around the latest version of KijiSchema.</p>
<h3>New: KijiExpress</h3>
<p>This version of the BentoBox is the first to contain KijiExpress, a Scala domain-specific language (DSL) for analyzing and modeling data stored in tables managed by KijiSchema. KijiExpress can be used to author complex flows of MapReduce jobs using a concise and expressive API.</p>
<p>KijiExpress is in the <tt>express/</tt> directory of the BentoBox. Its README includes instructions on running express jobs and scripts. A KijiExpress version of the <a href=http://docs.kiji.org/tutorials/express-recommendation/0.2.0/express-overview/>music recommendation tutorial</a> is also available in the <tt>examples/express-music</tt> directory. </p>
<h3>Notable updates to KijiSchema, KijiMR, the KijiMR Library, and the Kiji Hive Adapter</h3>
<p>A new release of KijiSchema, KijiMR, and the KijiMR library has been provided. This includes the following updates and changes:</p>
<ul>
<li><b>bin/kiji supports loading Hadoop distro-specific dependencies</b> by inferring from <tt>"bin/hadoop version"</tt> or <tt>$KIJI_HADOOP_DISTRO_VER</tt>.  </li>
<li>Added the ability to retrieve entity id from a <code>KijiTableKeyValueStore</code> reader. Call <code>KijiTableKeyValueStore.getTableForReader(reader)</code> to get the underlying KijiTable object.</li>
<li>Reorganize KijiMR project structure for multiple Hadoop distributions. KijiMR jars are now placed in <tt>$KIJI_MR_HOME/lib/distribution/hadoop2/</tt>. You can now optionally specify <classifier>hadoop2</classifer> on the KijiMR artifact to make your distribution requirement explicit.</li>
<li>Added a graph library to the KijiMR Library for developing item-category association mining models within Kiji</li>
<li>Kiji Hive Adapter now properly decodes complex Avro types, Avro unions, and map type families.</li>
</ul>
<h3>Conclusions</h3>
<p>We&#8217;re excited about the momentum building behind the BentoBox. New components, improved software stability, and a smoother upgrade process will help enable more powerful big data applications to be built with the BentoBox SDK.</p>
<p>Ready to get started? <a href="http://www.kiji.org/getstarted/#Downloads">Download the BentoBox</a> today!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/announcing-the-albacore-bentobox-v1.0.3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Versioned Data Structures and Avro</title>
		<link>http://www.kiji.org/2013/04/25/versioned-data-structures-and-avro/</link>
		<comments>http://www.kiji.org/2013/04/25/versioned-data-structures-and-avro/#comments</comments>
		<pubDate>Thu, 25 Apr 2013 21:03:48 +0000</pubDate>
		<dc:creator>Aaron Kimball</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1223</guid>
		<description><![CDATA[One of the biggest challenges in building a stable software system is maintaining backward compatibility with previous data formats. Systems like Kiji can help you maintain backward compatibility with your own data, but there are still some challenges involved in using all the features of Apache Avro while maintaining backward compatibility. This blog post will...  <a href="http://www.kiji.org/2013/04/25/versioned-data-structures-and-avro/" class="more-link" title="Read Versioned Data Structures and Avro">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead">One of the biggest challenges in building a stable software system is maintaining backward compatibility with previous data formats.</p>
<p>Systems like Kiji can help you maintain backward compatibility with your own data, but there are still some challenges involved in using all the features of Apache Avro while maintaining backward compatibility. This blog post will describe a common problem associated with storage and retrieval of Avro data, how we get around this problem in Kiji&#8217;s own data structures, and how you can use this technique as well.</p>
<h2>A Subtle Problem with SpecificRecords</h2>
<p>Like many applications that depend on Avro, Kiji uses its &#8220;SpecificRecord&#8221; API to generate custom classes representing data structures based on Avro IDL files. A custom SpecificRecord class would contain Java member fields for each field declared in the IDL file, getters, setters, as well as the Avro schema associated with the record.</p>
<p>For example, the following Avro IDL defines a record that holds a point:</p>
<div><tt>
<pre>record Point {
  float x;
  float y;
  string label;
}</pre>
<p></tt></div>
<p>This will be compiled to a Java class named <code>Point</code> that can deserialize, manipulate, and serialize Point instances.</p>
<p>Suppose you&#8217;ve used a system like Kiji to save some Point instances that you can manipulate later, and that you had the following method in your code:</p>
<div><tt>
<pre>/** Create a new point with x and y fields doubled. */
public Point doubleXYDistance(Point input) {
  // Initialize with all fields of the input Point
  Point.Builder builder = Point.newBuilder(input); 
  builder.setX(builder.getX() * 2.0);
  builder.setY(builder.getY() * 2.0);
  return builder.build();  
}</pre>
<p></tt></div>
<p>The call to <code>Point.newBuilder()</code> is initialized with fields from the input Point, so fields such as <code>label</code> are set to whatever the input record had. </p>
<p>Then suppose that in the next version of your program, you change the Avro IDL like so:</p>
<div><tt>
<pre>record Point {
  float x;
  float y;
  float z = 0.0;
  string label;
}</pre>
<p></tt></div>
<p>When this is recompiled you&#8217;ll have a &#8220;z&#8221; field, which will be gracefully added to existing records as you read them (when resolving the writer schema with this new reader schema). No problem. The <code>doubleXYDistance()</code> function will do the correct thing with z values as well; initializing the output Point instance with a z-value of 0 if the input Point lacks a z value, and using the input Point&#8217;s z value otherwise.</p>
<p>The main compatibility challenge occurs when you write out new records (with x, y, and z) and then an older application (compiled with the &#8220;2-d&#8221; version of Point) wants to manipulate them.</p>
<p>The older application can gracefully read 3-d points as 2-d points, discarding the z value. But consider this function:</p>
<div><tt>
<pre>void modifyPoint() {
  Point in = loadPointCellFromKiji();
  Point out = doubleXYDistance(in);
  persistPointToKijiCell(out);
}</pre>
<p></tt></div>
<p>When this writes a new Point object back to Kiji, it will write out a 2-d point! While the best thing would be for the system to accommodate additional newer fields gracefully in this process, the next best thing is to at least detect that you are operating on data that is too new, and refuse to do so before you corrupt the persistent information store.</p>
<h2>Protocol Versioning</h2>
<p>Kiji has this problem with <code>TableLayoutDesc</code> objects that represent Kiji table layouts as an Avro data structure. The KijiSchema shell modifies existing layouts by reading the TableLayoutDesc from the Kiji meta table, creating a modified copy, and persisting it back. We use Avro&#8217;s SpecificRecord interface to capture this.</p>
<p>One option to deal with this would be to use Avro&#8217;s GenericRecord API; it would allow us to faithfully copy all the fields of the input record into the output. If the new schema is backward compatible with the old schema (as is the case in those two versions of the <em>Point</em> record), we could work with the writer schema interpretation of the data directly.</p>
<p>But by using GenericRecord, we&#8217;d lose type-safe functions like <code>TableLayoutDesc.setName(String tableName)</code> (or <code>Point.setX(float x)</code>); we&#8217;d have to use the <code>GenericRecord.set(String fieldName, Object value)</code> method, which is a much more error-prone API to operate.</p>
<p>Instead, Kiji uses something we call <em>protocol versioning</em> to get around this issue. Each record type that we intend to operate on has a field named <code>version</code> which is a string. The Kiji TableLayoutDesc Avro record (what your JSON table layout files interact with) includes a <code>version</code> field which today you should set to <code>"layout-1.1"</code>.</p>
<p>In Kiji, a protocol version includes a <em>protocol name</em> and a version number in <em>major.minor.revision</em> format. The protocol name is a sanity check on what kind of record this version pertains to.  For example, Kiji table layouts all contain a protocol name of &#8220;layout&#8221;; this prevents the most basic error of trying to parse a similar but unrelated JSON record object in a place where it sholdn&#8217;t be.</p>
<p>The version number is a standard version number that follows <a href="http://semver.org">semantic versioning</a>: the major version changes when an incompatible change is introduced; the minor version for a compatible new feature; and the revision for a bug fix.</p>
<p>When we parse a JSON-formatted Avro record from a file, or load a serialized object into a SpecificRecord, we use the <a href="http://api-docs.kiji.org/kiji-schema/1.0.2/org/kiji/schema/util/ProtocolVersion.html">ProtocolVersion</a> class to parse the <tt>version</tt> field of the record. We can then use this to compare the minimum and maximum protocol versions tolerated by this version of Kiji itself to the record.</p>
<p>For example, the KijiSchema shell version 1.0.0 supports a maximum ProtocolVersion of <tt>layout-1.1.0</tt> for table layouts. It would refuse to operate on a Kiji TableLayoutDesc with <tt>version = "layout-1.5.0"</tt>. This TableLayoutDesc object might contain new fields that the SpecificRecord subclass compiled into KijiSchema Shell 1.0.0 would discard. The user would be directed to use a newer version of the shell to operate on the newer TableLayoutDesc record.</p>
<h2>Data Interpretation Semantics</h2>
<p>The notion of a protocol version goes beyond controlling the literal names and types of fields read and written by a given object. A protocol version might also govern the semantics of how an object is used.</p>
<p>For example, in Kiji, table layouts represented by TableLayoutDesc SpecificRecord objects are parsed by the <code>KijiTableLayout</code> class. This class performs a number of validity checks on the underlying TableLayoutDesc. As we want to guide users to stronger validity constraints, we need to make sure that newer versions of Kiji don&#8217;t refuse to operate with older persisted table layouts that fail to meet the new validity standards; a backwards-compatible mode must be employed to &#8220;grandfather in&#8221; any existing table layouts.</p>
<p>KijiTableLayout parses the ProtocolVersion from TableLayoutDesc.version and uses this to guide what semantics it imposes on table layouts. New table layouts that take advantage of the latest features might declare a higher-numbered protocol version that requires the new validity constraints. Old table layouts that use an older protocol version (like the current standard <tt>layout-1.1</tt>) would not be affected by these new rules. Of course, if you want to upgrade your table layout in a way that takes advantage of new features in the future, you&#8217;ll need to increment your protocol version &#8212; and possibly make other necessary adjustments to continue to conform to the current layout validation rules.</p>
<p>In the example above, you could imagine changing a protocol version in the Point example to denote that you now regard x and y values as being in meters instead of inches.</p>
<h3>Protocol versions elsewhere in Kiji</h3>
<p>We use the ProtocolVersion class in a number of places. For instance, if you <a href="http://api-docs.kiji.org/kiji-mapreduce-lib/1.0.0-rc6/org/kiji/mapreduce/lib/bulkimport/KijiTableImportDescriptor.html">write a JSON file</a> that controls how bulk imports map fields of an input CSV file into columns of a Kiji table, this JSON file also contains the protocol version <tt>"import-1.0"</tt>.</p>
<p>You can use this same JSON file to perform recurring imports from a data source indefinitely, while you periodically upgrade to new versions of KijiMR and the KijiMR library. While we might add new features that improve the bulk import process, an existing JSON import control file that declares a protocol version of <tt>import-1.0</tt> will be parsed and interpreted consistently.</p>
<h2>A Versioned Point</h2>
<p>How do you prevent yourself from falling into a similar trap yourself? Let&#8217;s return to the Point example from earlier. If from the start you had declared:</p>
<div><tt>
<pre>record Point {
  float x;
  float y;
  string label;
  string version; //  must be point-1.0
}</pre>
<p></tt></div>
<p>Then your application could rule out a large class of errors if you write:</p>
<div><tt>
<pre>private static final ProtocolVersion MAX_VER = ProtocolVersion.parse("point-1.0");

void modifyPoint() {
  Point in = loadPointCellFromKiji();
  if (MAX_VER.compareTo(ProtocolVersion.parse(in.getVersion()) < 0) {
    throw new RuntimeException("Input point is too new! Please upgrade the point modifier.");
  }
  Point out = doubleXYDistance(in);
  persistPointToKijiCell(out);
}</pre>
<p></tt></div>
<p>The ProtocolVersion class implements <tt>Comparable&lt;ProtocolVersion&gt;</tt>, so you can compare them easily without needing to worry about string parsing or comparison yourself.</p>
<p>Then when you declare your 3-d point:</p>
<div><tt>
<pre>record Point {
  float x;
  float y;
  float z = 0.0;
  string label;
  string version; //  must be point-1.1
}</pre>
<p></tt></div>
<p>... you would also change <code>MAX_VER</code> to <tt>"point-1.1"</tt>. The newer version of your software would work correctly with 3-d points, and the older version of your software would prevent itself from modifying them.</p>
<p>Note that in the Avro schema above, we don't declare the version field with a default value. We don't want Avro to automatically use the <em>reader's</em> default value here: we must use whatever <tt>version</tt> was persisted.</p>
<p>If you're retrofitting this behavior onto an older Avro data structure, you may need to gracefully handle a "null" default value for a new version field and treat it as the same as your "1.0.0" version.</p>
<h2>Conclusions</h2>
<p>Data compatibility is a difficult challenge to manage, and systems that make use of convenient and type-safe precompiled classes may be vulnerable to accidentally discarding or misinterpreting if they are not written carefully.</p>
<p>With Kiji, data compatibility is one of our primary concerns. We believe Kiji makes it easier to safely store large volumes of data in an evolvable fashion. But how applications manipulate and interpret that data can have a big impact on the final result. Avro's Generic and SpecificRecord interfaces offer different tradeoffs in the same flexibility/safety space, with GenericRecords offering you greater flexibility, while SpecificRecords offer a type-safe Java-friendly API.</p>
<p>Kiji uses SpecificRecord instances combined with this versioned protocol pattern to address this concern with its own data structures.</p>
<p>Curious to learn more about ProtocolVersion?</p>
<ul>
<li>Check out the <a href="http://api-docs.kiji.org/kiji-schema/1.0.2/org/kiji/schema/util/ProtocolVersion.html">javadoc</a> and consider using it in your software.</li>
<li>See its use in <a href="https://github.com/kijiproject/kiji-mapreduce-lib/blob/master/kiji-mapreduce-lib/src/main/java/org/kiji/mapreduce/lib/bulkimport/KijiTableImportDescriptor.java">KijiTableImportDescriptor</a>.</li>
<li><a href="http://www.kiji.org/getstarted/">Get started</a> hacking with Kiji!
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/2013/04/25/versioned-data-structures-and-avro/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing KijiSchema 1.0.2 and KijiMR rc61</title>
		<link>http://www.kiji.org/2013/04/22/announcing-kijischema-1-0-2-and-kijimr-rc61/</link>
		<comments>http://www.kiji.org/2013/04/22/announcing-kijischema-1-0-2-and-kijimr-rc61/#comments</comments>
		<pubDate>Tue, 23 Apr 2013 01:58:38 +0000</pubDate>
		<dc:creator>Milo Polte</dc:creator>
				<category><![CDATA[KijiMR]]></category>
		<category><![CDATA[KijiSchema]]></category>
		<category><![CDATA[Releases]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1215</guid>
		<description><![CDATA[New versions of KijiSchema (1.0.2) and KijiMR (rc61) have been released. This release is primarily incremental improvements and bug fixes to the APIs of both modules. In the next few weeks, users can expect another version of BentoBox incorporating both artifacts along with updated tutorials. Users who want to use them right now can update...  <a href="http://www.kiji.org/2013/04/22/announcing-kijischema-1-0-2-and-kijimr-rc61/" class="more-link" title="Read Announcing KijiSchema 1.0.2 and KijiMR rc61">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead">New versions of KijiSchema (1.0.2) and KijiMR (rc61) have been released.</p>
<p>This release is primarily incremental improvements and bug fixes to the APIs of both modules. In the next few weeks, users can expect another version of BentoBox incorporating both artifacts along with updated tutorials. Users who want to use them right now can update the versions in their pom.xml files (ask on the kiji user mailing list for help).</p>
<h3>Notable changes</h3>
<ul>
<li><b>Row filter improvements</b> have been made in both modules. RowFilters will now be correctly serialized into KijiMR jobs (Thanks to Jeff Kolesky for contributing to this).</li>
<li><b>KijiTableKeyValueStore reader now uses EntityId keys</b> instead of strings. This is an incompatible change from previous versions of the class in KijiMR.</li>
<li>Bug fixes for KijiPager and KijiMR job set-up.</li>
<li>The deprecated <code>getEntityId()</code> method has been removed from ProducerContext. Producers needing the entity id should retrieve it with <code>KijiRowData.getEntityId()</code> in their <code>produce()</code> methods instead.</li>
</ul>
<p>As always, full release notes can be found in RELEASE_NOTES.txt at the top level of both modules.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/2013/04/22/announcing-kijischema-1-0-2-and-kijimr-rc61/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing the &#8220;Albacore&#8221; BentoBox</title>
		<link>http://www.kiji.org/2013/04/09/announcing-the-albacore-bentobox/</link>
		<comments>http://www.kiji.org/2013/04/09/announcing-the-albacore-bentobox/#comments</comments>
		<pubDate>Wed, 10 Apr 2013 00:11:34 +0000</pubDate>
		<dc:creator>Aaron Kimball</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1186</guid>
		<description><![CDATA[Announcing the &#8220;Albacore&#8221; BentoBox We are pleased to announce that you can now download a new version of the BentoBox SDK for Kiji. This system includes several upgraded components and will make it easier to deliver new releases of Kiji software to you as well. We are shifting how we version and release BentoBoxes: approximately...  <a href="http://www.kiji.org/2013/04/09/announcing-the-albacore-bentobox/" class="more-link" title="Read Announcing the &#8220;Albacore&#8221; BentoBox">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead">Announcing the &#8220;Albacore&#8221; BentoBox</p>
<p>We are pleased to announce that you can now <a href="http://archive.kiji.org/tarballs/kiji-bento-albacore-1.0.1-release.tar.gz">download a new version of the BentoBox SDK</a> for Kiji. This system includes several upgraded components and will make it easier to deliver new releases of Kiji software to you as well.</p>
<p>We are shifting how we version and release BentoBoxes: approximately each quarter, a new minor version (1.0 -&gt; 1.1 -&gt; 1.2) of the BentoBox will be released. Each such version has a name &#8212; in keeping with our overall theme, they&#8217;ll be named after sushi. This BentoBox release is called &#8220;Albacore.&#8221;</p>
<p>Albacore includes the following software:</p>
<ul>
<li>KijiSchema 1.0.1</li>
<li>KijiSchema shell 1.0.0</li>
<li>KijiMR 1.0.0-rc6</li>
<li>KijiMR Library 1.0.0-rc6</li>
<li>Kiji Hive adapter 0.1.1</li>
<li>Example code: phonebook and music recommendation tutorials</li>
</ul>
<p>This BentoBox is powered by Hadoop and HBase via CDH 4.1. It is built around the latest version of KijiSchema, which is effectively the same as the KijiSchema 1.0.0 release made last week.</p>
<h3>BentoBox improvements</h3>
<p>The BentoBox system has been revamped with a new <b><tt>bento upgrade</tt></b> command. When a new version of the BentoBox is available, just type <tt>bento upgrade</tt> and the new SDK will be downloaded and installed in place (don&#8217;t worry, we make a backup of your old BentoBox and data first).</p>
<p>BentoBox instances will periodically check for available updates and notify you when they&#8217;re available. You can then do an in-place upgrade with a single command.</p>
<p>The BentoBox now contains several components. To help you keep track of which version of each you&#8217;re running, the <tt>bento-version.txt</tt> file will provide you with a manifest.</p>
<h4>Component upgrades</h4>
<p>Going forward, each minor version of the BentoBox may include new minor versions of stable software we release (e.g., BentoBox 1.1 may contain KijiSchema 1.1 or 1.2, not 1.0).</p>
<p>Periodic revisions of the BentoBox (1.0.1, 1.0.2, etc) will include only revisions of stable components like KijiSchema (1.0.1, 1.0.2, 1.0.3, etc.). Experimental components like the Kiji Hive adapter, or &#8220;release candidate&#8221; components like KijiMR may be upgraded more aggressively.</p>
<h3>New: A Hive Adapter for Kiji</h3>
<p>This version of the BentoBox is the first to contain the new Kiji Hive adapter. This plugin for Hive allows you to run HiveQL queries against tables managed by KijiSchema.</p>
<p>The Kiji Hive adapter is in the <tt>hive-adapter/</tt> directory of the BentoBox. Its README includes some example queries you can run against the table generated by the <a href="http://docs.kiji.org/tutorials/music-recommendation/1.0.0-rc6/music-overview/">music recommendation tutorial</a>.</p>
<h3>Updates to KijiMR and KijiMR Library</h3>
<p>A new release of KijiMR and the KijiMR library has been provided. This includes the following updates and changes:</p>
<ul>
<li>A <b>new XML bulk importer</b> is included (<tt>XMLBulkImporter</tt>).</li>
<li>You can <b>run bulk imports from the KijiSchema shell</b> now. See <a href="http://docs.kiji.org/userguides/mapreduce/1.0.0-rc6/bulk-importers/">the KijiMR bulk importers user guide</a> for more information.</li>
<li>The <tt>MapReduceJob</tt> class has been renamed to <tt>KijiMapReduceJob</tt>.</li>
<li>Your implementations of <tt>KijiProducer</tt> should now use <tt>KijiTableContext.getEntityIdFactory()</tt> to create entity ids; <tt>ProducerContext.getEntityId()</tt> is now deprecated and will be removed soon.</li>
<li>Some other minor improvements or changes to the API have been made; see the release notes for full details.</li>
</ul>
<h3>Conclusions</h3>
<p>We&#8217;re excited about the momentum building behind the BentoBox. New components, improved software stability, and a smoother upgrade process will help enable more powerful big data applications to be built with the BentoBox SDK.</p>
<p>Ready to get started? <a href="http://www.kiji.org/getstarted/#Downloads">Download the BentoBox</a> today!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/2013/04/09/announcing-the-albacore-bentobox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>KijiSchema Stable API Compatibility</title>
		<link>http://www.kiji.org/2013/04/04/kijischema-stable-api-compatibility/</link>
		<comments>http://www.kiji.org/2013/04/04/kijischema-stable-api-compatibility/#comments</comments>
		<pubDate>Thu, 04 Apr 2013 15:00:50 +0000</pubDate>
		<dc:creator>Aaron Kimball</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1172</guid>
		<description><![CDATA[KijiSchema 1.0.0 is the first version of KijiSchema to drop the &#8220;rc&#8221; label. From this point forward, we expect to impose significantly more strict requirements on our commitment to API compatibility. KijiSchema is the first such module to be subject to these requirements; over the coming months, we expect to go through a similar process...  <a href="http://www.kiji.org/2013/04/04/kijischema-stable-api-compatibility/" class="more-link" title="Read KijiSchema Stable API Compatibility">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead">KijiSchema 1.0.0 is the first version of KijiSchema to drop the &#8220;rc&#8221; label. From this point forward, we expect to impose significantly more strict requirements on our commitment to API compatibility.</p>
<p>KijiSchema is the first such module to be subject to these requirements; over the coming months, we expect to go through a similar process of more volatile changes followed by a stabilization period for KijiMR. The result of that process will be KijiMR 1.0.0. The next version of KijiMR to be released is 1.0.0-rc6.</p>
<p>There are several important considerations for compatibility. This document will discuss:</p>
<ul>
<li>API version compatibility within KijiSchema and other post-1.0.0 modules</li>
<li>Version compatibility between modules (e.g., KijiSchema and KijiMR)</li>
<li>Our plan for new module release versioning</li>
<li>The future of Kiji Bento Box releases</li>
</ul>
<p>This document is somewhat long, but forms a contract of sorts, so you should read it. We want to be upfront about our expectations for everyone. This document is written both for the developers of Kiji, and for its users; by adhering to the standards and requirements stated here, we hope to minimize disruption in existing projects within and depending on Kiji while continuing to enable new features, and empower users to determine for themselves when they want to upgrade between versions of individual Kiji modules.</p>
<p>Read on to learn more.<br />
<span id="more-1172"></span></p>
<h2>API Compatibility Within a Module</h2>
<p>Our goal is to release stable APIs while continuing to provide new features to users. What it means for an API to remain &#8220;stable&#8221; is set forth on our wiki, along with some guidelines for how to achieve this in Java code: <a href="https://github.com/kijiproject/wiki/wiki/Api-Compatibility">https://github.com/kijiproject/wiki/wiki/Api-Compatibility </a></p>
<p>When releasing new versions of KijiSchema (or any future stable module), we will reason about how changes impact the version number as follows:</p>
<ul>
<li>An increase in the revision number (1.0.0 to 1.0.1) contains only bug fixes, or very safe, well-tested and noninvasive compatible improvements or new features.</li>
<li>An increase in the minor version (1.0.x to 1.1.0) contains general bug fixes and compatible new features and improvements.</li>
<li>An increase in the major version (1.x.y to 2.0.0) contains incompatible API changes and may require upgrades to lower-level aspects of the system like recorded metadata formats too.</li>
</ul>
<p>What it means to be a &#8220;compatible&#8221; API change is defined below.</p>
<p>Each module like KijiSchema contains a large number of APIs that are intended for use by different audiences. The flexibility we have in enhancing KijiSchema is at odds with our requirements that some elements stay the same. At the same time, while we want to ensure that compatibility remains between versions, to do so too rigidly would rule out the gradual introduction of experimental features, which might need to change significantly (or be deprecated altogether) within a few versions. While through visibility modifiers like &#8220;public&#8221; and &#8220;private&#8221; Java enables us to enforce some of the boundaries of our API, there are other cases where this is not possible (e.g., a &#8220;private&#8221; class that needs to be used in two internal packages must be declared &#8220;public&#8221;). And Java does not allow us to express the stable-vs-experimental distinction directly at all.</p>
<p>We intend to broadly follow the contract set forth in semantic versioning (<a href="http://semver.org">semver.org</a>), but to do so, must define our APIs more specifically than the Java compiler would naturally enforce.</p>
<p>Our compromise is to use a set of Java annotations on all our classes. These are declared in the annotations module here: <a href="http://github.com/kijiproject/annotations">http://github.com/kijiproject/annotations</a>. When using classes declared in Kiji modules, please refer to the Javadoc to check for the associated annotations:</p>
<p>For example, the javadoc for the interface org.kiji.schema.Kiji starts as follows:</p>
<h4>org.kiji.schema</h4>
<h1>Interface Kiji</h1>
<p><b>All Superinterfaces:</b><br/>KijiTableFactory, ReferenceCountable&lt;Kiji&gt;<br/><b>All Known Implementing Classes:</b><br/>HBaseKiji<br/></p>
<hr/>
@ApiAudience.Public<br/>@ApiStability.Stable<br/>@Inheritance.Sealed<br/>public interface <b>Kiji</b><br/>extends KijiTableFactory, ReferenceCountable&lt;Kiji&gt;</p>
<p>This interface uses all three of our annotation types: ApiAudience, ApiStability, and Inheritance.</p>
<p>One set of annotations describes the intended <i>audience</i> of a piece of code. The audiences are as follows:</p>
<ul>
<li><b>@ApiAudience.Public</b> &#8211; This class is intended for use by everyone. It is held to our highest stability requirement.</li>
<li><b>@ApiAudience.Framework</b>  &#8211; This class is intended for use only by other Kiji framework modules (like KijiMR). Framework-level classes may change in incompatible ways between minor versions (1.1.x to 1.2.0). Developers using framework-level classes should monitor dev@kiji.org and the issue tracker at jira.kiji.org for changes. End-users may find these APIs lower level than are expected for their consumption.</li>
<li><b>@ApiAudience.Private</b>  &#8211; Only other classes in the same module (KijiSchema) are expected to access this implementation detail. No guarantees are made about stability.</li>
</ul>
<p>Within our source code, several classes are declared in packages named &#8220;impl&#8221; (e.g., org.kiji.schema.impl). Any class in an &#8220;impl&#8221; package, or whose name ends in Impl (org.kiji.schema.impl.Foo, or org.kiji.schema.BarImpl) is an implementation detail; it is implicitly the same as ApiAudience.Private, though this may not be explicitly labeled.</p>
<p>Several classes are declared in packages named &#8220;org.kiji.*.framework&#8221; and are implicitly @ApiAudience.Framework-level classes, though they are typically labeled as well.</p>
<p>Each class also declares the <i>stability level</i> we believe we can provide. Over time, classes are expected to &#8220;graduate&#8221; to the most stable level. New experimental code is described as such as well. Our stability levels are described as follows:</p>
<ul>
<li><b>@ApiStability.Experimental</b> &#8211; This is brand new and, even if its audience is intended to be public, it may change in incompatible ways between any versions (like 1.0.2 and 1.0.3). You should pay close attention to development mailing lists if you use any of these features, and provide feedback.</li>
<li><b>@ApiStability.Evolving</b> &#8211; APIs that are no longer experimental, and we believe will be stable &#8220;soon.&#8221; These APIs may evolve incompatibly between minor versions (1.1.x and 1.2.0). Classes marked ApiAudience.Public have a high burden of proof to justify an incompatible change in this state, but sometimes a change may be required.</li>
<li><b>@ApiStability.Stable</b> &#8211; The most mature, trusted, and heavily-used APIs have this annotation. If the class is marked ApiAudience.Public, an incompatible change to such a class would only come at the introduction of a new major version (2.0.0), or would be seen as a regression to fix. Framework-level classes may see changes between minor versions, but the burden to justify doing so is very high.</li>
<li><b>@Deprecated</b> &#8211; This Java annotation describes a class or method whose use is no longer preferred, and which may not be maintained over time. Classes and methods marked as @Deprecated during a release candidate may be removed in a later minor version. After 1.0.0, classes/methods marked as @ApiAudience.Public and subsequently marked @Deprecated will be removed only in 2.0.0. They may cease to interoperate with new features before this time.</li>
</ul>
<p>Neither Java&#8217;s &#8220;interface&#8221; keyword nor abstract classes distinguish between interfaces that hide library functionality from its clients (APIs), and interfaces that clients are expected to implement and provide as &#8220;callbacks&#8221; into the library itself (SPIs). Depending on how an interface is intended to be used, what it means to evolve the interface in a stable fashion changes.</p>
<p>We declare a final set of annotations that describes how we expect clients to reason about <il>inheritance</i> of a class:</p>
<ul>
<li><b>@Inheritance.Sealed</b> &#8211; We expect that the module itself provides all implementations of this interface (or extensions of this abstract class). For example, we do not expect users to implement org.kiji.schema.KijiTableWriter. If you implement this interface yourself, you risk an incompatible change.</li>
<li><b>@Inheritance.Extensible</b> &#8211; Users are permitted to extend this class or interface. For example, we expect that you will provide implementations of org.kiji.mapreduce.gather.KijiGatherer.</li>
</ul>
<p>Sealed interfaces may have new methods added to them between versions. We expect that you will call methods of these interfaces, not implement them yourself.</p>
<p>Since you provide implementations of extensible interfaces, you may expect that we will not add a new abstract method definition to the interface&#8211;but we may deprecate a method we do not intend to call in the future.</p>
<p>Classes not otherwise marked should be implicitly considered @ApiAudience.Private and  @Inheritance.Sealed. Please point out any such non-impl classes; we will mark them explicitly.</p>
<p>For many classes and methods, our Javadoc defines our API contracts more precisely. Areas where the Javadoc is ambiguous are subject to change, and we appreciate questions regarding their assumptions.</p>
<h3>The bottom line:</h3>
<ul>
<li>If you use a class declared @ApiAudience.Public and @ApiStability.Stable, your usage is guaranteed up to version 2.0.0.</li>
<li>If you use a class declared @ApiAudience.Public and @ApiStability.Evolving (or @ApiAudience.Framework), there may be incompatible changes (though we endeavor not to).</li>
<li>If it is marked @ApiStability.Experimental, all bets are off.</li>
<li>The publicity and stability level of classes can increase over time. If you feel that a class advertised as framework-only is useful to end users, please discuss on dev@kiji.org. We can always make things &#8220;more public&#8221; if there is a justification for doing so, or create a safe public wrapper around the API in question.</li>
</ul>
<h2>Version Compatibility Between Modules</h2>
<p>Different modules (e.g., KijiSchema and KijiMR) may rely on one another. This section describes how you may reason about which versions can interoperate with one another.</p>
<p>These modules may rely on @ApiAudience.Framework-level classes between one another to communicate. These classes may change in incompatible ways between minor versions (1.2 to 1.3).</p>
<p>Prior to 4/1/2013, all available modules had synchronized &#8220;rc&#8221; version numbers. Going forward, the version numbers of one module will have little or nothing to do with version numbers of another. KijiSchema may reach 1.3.0 much more quickly than KijiMR. The reverse may also be true.</p>
<p>KijiMR depends on KijiSchema. A given release of KijiMR will depend on some minor version of KijiSchema. It will interoperate correctly with all revisions in that minor version, but may not work correctly with the next minor version of KijiSchema. Cross-minor-version compatibility between modules is a goal of ours, but not necessarily a blocker to release.</p>
<p><i>For example:</i><br/><br />
Suppose KijiMR 1.2.0 depends on KijiSchema 1.3.0.</p>
<p>Subsequent revisions of KijiSchema (1.3.1, 1.3.2) will interoperate correctly. No guarantee is made about the next minor version (KijiSchema 1.4.0).</p>
<p>When the next minor version of a module is released, we will announce which versions of related modules it can interoperate with. For example, if KijiSchema 1.4.0 turned out to be compatible with KijiMR 1.2.0, we would announce that fact. Otherwise, expect KijiMR 1.3.0 to be released shortly. At that time, we would specify whether KijiMR 1.3.0 would interoperate with both KijiSchema 1.4.0 and 1.3.x, or only with 1.4.0.</p>
<h2>New module release versioning</h2>
<p>Throughout 2013, we expect to continue adding to the Kiji ecosystem. Additional components will provide new functionality. KijiSchema and KijiMR were based heavily on existing code from the WibiData codebase. When we released these components under the Kiji flag, we took the opportunity to refactor what we could, but wanted to reflect that the majority of the functionality was known, already implemented, and formed a relatively &#8220;complete&#8221; offering: thus the &#8220;1.0.0-rc&#8221; versioning. Additional rearchitecting was required to react to our new open source home, a process that we thank you for your patience in. These modules moved through a series of &#8220;release candidates&#8221; which reflected points in time during this refactoring.</p>
<p>New components under development will not be released with the &#8220;1.0.0-rc1&#8243; designation. Such new components will be released with version numbers starting from 0.1.0 as designated by Semantic Versioning (<a href="http://semver.org">semver.org</a>). For such projects, stability will not be defined until version 1.0.0.</p>
<p>New features may introduce incompatible changes between 0.1.0 and 0.2.0. Where possible, we will endeavor to leave a &#8220;leapfrog&#8221; path open to you for migration. </p>
<p><i>For example:</i></p>
<p>KijiRocketship is the highest performance realest-real-time way to get to the moon and back.</p>
<ul>
<li>The first version is 0.1.0.</li>
<li>An API (<tt>org.kiji.rocket.Engine.fireJets()</tt>) may be introduced in version 0.2.0.</li>
<li>A preferred API (<tt.Engine.fireJets(int numJets)</tt>) may be introduced in version 0.3.0. The original API (<tt>fireJets()</tt>) will be marked @Deprecated. The Javadoc will note the version number when deprecation happens, and what you should use instead.</li>
<li>The original API will be removed at 0.4.0 or afterward.</li>
</ul>
<p>This will allow clients of KijiRocketship to test changes with an existing release, rather than need to make all new changes immediately to evaluate the next release. We cannot guarantee that we can do this in all cases between 0.x and 0.(x+1), but will make a reasonable attempt to do so. Cases where incompatible changes are introduced will be noted in the release notes.</p>
<h2>Future Kiji BentoBox Releases</h2>
<p>The Kiji BentoBox is our SDK for developing Big Data Applications on top of Kiji. We have thus far created a new "rc" release for the bento box with each release of KijiSchema. In the future, bento box versions will be decoupled from an association with any particular Kiji module.</p>
<p>Individual modules will be released when it makes sense to do so for that given module, on a rolling basis. The BentoBox will see a new minor release (1.1, 1.2, etc) approximately every quarter. Along with a minor version number, we will also apply an alphabetical name to each release; like the versions of Android, Ubuntu, and other projects, the names will increase alphabetically (a, b, c...) each time. In keeping with our sushi theme, we'll name these after fish. Kiji BentoBox 1.0.0 "albacore" will be released shortly.</p>
<p>Each new minor version of the BentoBox will include a complete set of compatible Kiji modules; the most recent stable versions of each module that are compatible with one another will be included.</p>
<p>Revisions of the BentoBox (1.1.1, 1.1.2, etc) may be produced more frequently. These revisions will correct bugs in the Bento packaging or scripts itself. Stable modules (e.g., KijiSchema) will be upgraded only very conservatively (new revisions only) in such releases of the BentoBox. Unstable modules (version numbers like 1.0.0-rcX, or 0.x.y) will be upgraded more aggressively in such point releases; if you are developing against unstable modules, it is important that you keep up to date with your dependencies.</p>
<h2>Conclusions</h2>
<p>Thank you for reading this far. This "contract" clarifies how we intend to balance the desire for new features, experimentation, and agile open source development with the requirement for stability and predictability in the interfaces you depend on. In this and all Kiji development matters, we welcome your participation in this process and our discussions. We hope to continue to serve you in your Big Data needs and thank you for making Kiji a part of your system. Please direct any questions or oversights to user@kiji.org. It's likely that others would benefit from hearing the answers to any questions you have. And look forward to Bento Albacore soon!</p>
<p>Ready to try out Kiji now? <a href="http://www.kiji.org/getstarted/#Downloads">Download the BentoBox today!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/2013/04/04/kijischema-stable-api-compatibility/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing KijiSchema 1.0.0</title>
		<link>http://www.kiji.org/2013/04/02/announcing-kijischema-1-0-0/</link>
		<comments>http://www.kiji.org/2013/04/02/announcing-kijischema-1-0-0/#comments</comments>
		<pubDate>Wed, 03 Apr 2013 00:32:22 +0000</pubDate>
		<dc:creator>Aaron Kimball</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1169</guid>
		<description><![CDATA[We are proud to announce the immediate availability of KijiSchema 1.0.0. You can use this in your Maven projects, or download it from http://www.kiji.org/getstarted/. A BentoBox containing KijiSchema 1.0.0 (and the next release of KijiMR and some other goodies) will be available within a couple weeks. KijiSchema 1.0.0 represents the first stable API for this...  <a href="http://www.kiji.org/2013/04/02/announcing-kijischema-1-0-0/" class="more-link" title="Read Announcing KijiSchema 1.0.0">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead">We are proud to announce the immediate availability of KijiSchema 1.0.0.</p>
<p>You can use this in your Maven projects, or download it from <a href="http://www.kiji.org/getstarted/">http://www.kiji.org/getstarted/</a>.</p>
<p>A BentoBox containing KijiSchema 1.0.0 (and the next release of KijiMR and some other goodies) will be available within a couple weeks.</p>
<p>KijiSchema 1.0.0 represents the first stable API for this component; subsequent versions of KijiSchema will contain new features or improvements but compatibility with existing releases will be preserved. A longer message about this subject and the precise specifications of &#8220;compatible&#8221; and &#8220;stable&#8221; will be released tomorrow.</p>
<p>KijiSchema 1.0.0 includes a few important new features and changes since rc5. The degree of incompatible changes should be very modest.</p>
<ul>
<li><b>The <tt>close()</tt> method (deprecated in rc5) has been removed from KijiTable.</b> You must now use <tt>KijiTable.release()</tt>. This is the biggest incompatible change in this release that most users will see.</li>
<li><b>A new <tt>KijiBufferedWriter</tt> class</b> allows you to buffer and transmit a number of writes to a Kiji table in batch for improved performance.</li>
<li><b>Documentation (especially Javadoc) has been improved</b> in a number of cases. We have attempted to specify more precisely how most of our core classes work.</li>
<li><b>Stability annotations</b> (Experimental, Evolving, or Stable) have been added to all classes.</li>
<li>As a bug fix, <tt>get()</tt> and <tt>scan()</tt> operations on empty tables with no column families now return empty responses/scanners, rather than null.</li>
<li>A few other bug fixes and tune-ups throughout.</li>
<li>Note that many classes marked <tt>@Deprecated</tt> in the KijiSchema release candidates have been removed, but others persist. <b>These classes may be removed soon</b>&#8211;in particular, the <tt>org.kiji.schema.mapreduce package</tt>. Please use KijiMR for your MapReduce needs. (If you upgrade to KijiSchema 1.0.0, your code should compile without any deprecation warnings.)</li>
</ul>
<p>All users are encouraged to promptly upgrade to KijiSchema 1.0.0. Usage of any &#8220;release candidate&#8221; editions of KijiSchema is heavily discouraged, as they are not compatible with the ongoing world. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/2013/04/02/announcing-kijischema-1-0-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bulk Importing in KijiMR</title>
		<link>http://www.kiji.org/2013/03/21/bulk-importing-in-kijimr/</link>
		<comments>http://www.kiji.org/2013/03/21/bulk-importing-in-kijimr/#comments</comments>
		<pubDate>Thu, 21 Mar 2013 17:00:43 +0000</pubDate>
		<dc:creator>Lee Sheng</dc:creator>
				<category><![CDATA[KijiMR]]></category>
		<category><![CDATA[importing]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1082</guid>
		<description><![CDATA[One of the most important considerations when using any kind of data store is how to get your data into the store. While abstraction layers like KijiSchema are useful for avoiding the need to understand the underlying implementation details of the HBase in the random access use case, bulk importing data often involves huge datasets...  <a href="http://www.kiji.org/2013/03/21/bulk-importing-in-kijimr/" class="more-link" title="Read Bulk Importing in KijiMR">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead">One of the most important considerations when using any kind of data store is how to get your data into the store.  While abstraction layers like KijiSchema are useful for avoiding the need to understand the underlying implementation details of the HBase in the random access use case, bulk importing data often involves huge datasets that warrants special consideration from both a performance and an operational perspective.  In addition, we’ll also walk through a real world use case of bulk importing some actual data.</p>
<p>While we have a variety of canned bulk importers described in the <a href="http://docs.kiji.org/userguides/mapreduce/1.0.0-rc5/bulk-importers/">bulk importer userguide</a> for parsing and importing various common file formats, there are other important job configuration parameters for how the imports are executed.</p>
<h3>Option 1: Using the KijiSchema PUT API</h3>
<p>In direct writing mode, KijiMR will create a MapReduce job that reads over the input and generates the desired put(s) associated with each entry in the data.  These puts are directly applied to a Kiji table as the job progresses.</p>
<h4>Benefits:</h4>
<li>Ability to run this safely on an active cluster.</li>
<li>The data that has been loaded is available immediately while the job is in progress.</li>
<h4>Drawbacks:</h4>
<li>If this job fails partway for any reason, we’ll have partially loaded data.</li>
<li>This would involve generating writes for every entity, which may result in potentially significant write load on the cluster.</li>
<li>Since Kiji doesn’t yet support atomic writes to the same row(<a href="https://jira.kiji.org/browse/SCHEMA-189">but this is coming soon</a>), bulk importers will generate a write for each individual cell, even if they are associated with the same row.  This would result in greater disk utilization.</li>
<h3>Option 2: Bulk Loading using HFiles</h3>
<p>For bulk loading, Kiji can create a MapReduce job that reads over the input and generates HFiles containing the rows that can be loaded directly into HBase using their <a href="http://hbase.apache.org/book/arch.bulk.load.html">bulk load</a> functionality.  Once the job completes, the HFiles can be loaded into the Kiji table to allow them to be accessed.</p>
<h4>Benefits:</h4>
<li>Atomicity for committing on the job.  Either we get everything or we get nothing.</li>
<li>Orders of magnitude faster (see comparison below).</li>
<h4>Drawbacks:</h4>
<li>As a result of the ordering of the StoreFiles, this could trigger a compaction on running clusters, which could be painful on large clusters.  See the commentary in <a href="https://issues.apache.org/jira/browse/HBASE-3404" title="HBASE-3404">HBASE-3404</a> for more information.</li>
<h3>My Recommendation</h3>
<p>For a new cluster, the recommended practice is to bulk load via HFiles.  This allows for the initial backlog of data to be imported quickly, while avoiding the compaction issues above(since there’s no data in the cluster).  If this bulk import job is for an existing Kiji instance, using the direct puts will allow the existing cluster to continue to respond to requests while still accepting the new data.</p>
<h2>The Test Drive</h2>
<p>As part of my testing of this new functionality, I tried bulk importing some of the sample data from the <a href="http://www.kaggle.com/c/bluebook-for-bulldozers">Kaggle Blue Book for Bulldozers</a> challenge.  This data came in a CSV file with a header that contained 401,126 lines including the header.  The header line contains the names of the 53 fields.  The rest of this example assumes that you have a <a href="http://www.kiji.org/getstarted/#Installation">bento box and a Kiji instance installed</a>.</p>
<p>Specifying the layout to create a Kiji table with this many columns would have required a rather long-winded DDL.  Since we need at least one row for each column family:qualifier, this would involve a lot of tedious copy and pasting.  To accelerate this process, I wrote a little script: <a href="https://gist.github.com/lsheng/5165785">generate-ddl.sh</a> that takes in said CSV file, parses the header, and auto-generates a default DDL assuming that every field is a string.  Then the user could simply modify this generated DDL and produce the layout that they are looking for.  Once we are happy with this, we can create the table using the kiji-schema-shell:</p>
<pre>./generate-ddl.sh Train.csv > Train.ddl
kiji-schema-shell --file=Train.ddl</pre>
<p>The <a href="http://docs.kiji.org/apidocs/kiji-mapreduce-lib/1.0.0-rc5/org/kiji/mapreduce/lib/bulkimport/CSVBulkImporter.html">CSVBulkImporter</a> requires an import descriptor that defines the mapping from the source fields in the CSV to the destination Kiji columns.  Being that this is also dependent on the fields, I’ve written another little script <a href="https://gist.github.com/lsheng/5165799">generate-import-descriptor.sh</a> that takes in said CSV file, parses the header, and autogenerates a default import descriptor JSON file.</p>
<pre>./generate-import-descriptor.sh Train.csv > Train.json
hadoop fs -copyFromLocal Train.json /</pre>
<p>Finally we need to trim the header from the data file that we wish to bulk-import, and copy it over to HDFS so that the MapReduce job can get at it.</p>
<pre>tail -n +2 Train.csv > Train-no-header.csv
hadoop fs -copyFromLocal Train-no-header.csv /</pre>
<h3>With Option 1: Using the KijiSchema PUT API</h3>
<p>We can use Kiji to create a bulk importer job whose output is a kiji table(note the &#8211;output parameter).</p>
<pre>kiji bulk-import \
  -Dkiji.import.text.column.header_row=`head -1 Train.csv` \
  -Dkiji.import.text.input.descriptor.path=/Train.json \
  --importer=org.kiji.mapreduce.lib.bulkimport.CSVBulkImporter \
  --output="format=kiji table=kiji://.env/default/train nsplits=1" \
  --input="format=text file=/Train-no-header.csv"</pre>
<p>This took 78 minutes on a bento cluster running on my local machine, and consumed 3.2g disk space.  </p>
<h3>With Option 2: Bulk loading via HFiles</h3>
<p>Alternately, we can use Kiji to create a bulk importer whose output is a kiji table.  Note that the main difference here is that the &#8211;output parameter has changed to using the hfile format and that we specify the destination HFile. Note: we still need a table to know what layout the HFile should use.</p>
<pre>kiji bulk-import \
  -Dkiji.import.text.column.header_row=`head -1 data/Train.csv` \
  -Dkiji.import.text.input.descriptor.path=/Train.json \
  --importer=org.kiji.mapreduce.lib.bulkimport.CSVBulkImporter \
  --output="format=hfile table=kiji://.env/default/train nsplits=1 file=hdfs://localhost:8020/train.bulkload" \
  --input="format=text file=/Train-no-header.csv"</pre>
<p>Finally once these files get created, they can be bulk loaded with the bulk-load tool: </p>
<pre>kiji bulk-load \
  --hfile=hdfs://localhost:8020/train.bulkload/part-r-00000.hfile \
  --table=kiji://.env/default/train</pre>
<p>This took 2 minutes on a bento cluster running on my local machine, and consumed 483.4m disk space. This is vastly (50x) faster than the individual PUTs on my little laptop.</p>
<p>Now all of this data has been loaded into Kiji to do whatever you might like for post processing!</p>
<h2>Performance Stats</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th colspan="2">Method</th>
<th>Processing Time (min.)</th>
<th>Memory Usage</th>
</tr>
</thead>
<tbody>
<tr class="success">
<td colspan="2">Using KijiSchema PUTs</td>
<td align="right">78</td>
<td align="right">3.20 GB</td>
</tr>
<tr class="info">
<td colspan="2">Bulk Loading using HFiles</td>
<td align="right">2</td>
<td align="right">0.47 GB</td>
</tr>
</tbody>
</table>
<p>Above are the results for bulk importing of data into uncompressed Kiji tables.  As you can see there&#8217;s nearly a 40x difference between bulk import time, and a 6x difference in the disk utilization.  Using HFiles to bulk import data is more performant than doing direct writes, but there are potential operational difficulties on a running cluster with the possibly of an (expensive) compaction looming when the data files are loaded.</p>
<h2>Addendum: Timestamps</h2>
<p>In <a href="http://www.kiji.org/2013/02/13/common-pitfalls-of-timestamps-in-hbase/" title="Common Pitfalls of Timestamps in HBase">Common Pitfallfalls of Timestamps in HBase</a>, we discuss many of the potential pain points of dealing with timestamps within HBase.  While in general we don’t recommend manually setting timestamps, in the case of the initial bulk importing of data, it&#8217;s often beneficial to backfill the timestamps based on the data to be imported.  This way initial imported data can have the same behavior as newly added data in your application.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/2013/03/21/bulk-importing-in-kijimr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing KijiSchema 1.0.0-rc5</title>
		<link>http://www.kiji.org/2013/03/15/announcing-kijischema-1-0-0-rc5</link>
		<comments>http://www.kiji.org/2013/03/15/announcing-kijischema-1-0-0-rc5#comments</comments>
		<pubDate>Fri, 15 Mar 2013 22:26:41 +0000</pubDate>
		<dc:creator>Milo Polte</dc:creator>
				<category><![CDATA[KijiSchema]]></category>
		<category><![CDATA[Releases]]></category>

		<guid isPermaLink="false">http://www.kiji.org/?p=1142</guid>
		<description><![CDATA[A new version of KijiSchema (1.0.0-rc5) has been released! This version of KijiSchema continues the maturation process of the KijiSchema framework&#8217;s API. The improvements from the previous version are primarily internal and incremental. Wherever possible, previous functionality has been kept and marked as deprecated rather than removed. Users should see fewer dramatic user-facing alterations than...  <a href="http://www.kiji.org/2013/03/15/announcing-kijischema-1-0-0-rc5" class="more-link" title="Read Announcing KijiSchema 1.0.0-rc5">Read more &#187;</a>]]></description>
				<content:encoded><![CDATA[<p class="lead">A new version of KijiSchema (1.0.0-rc5) has been released!</p>
<p>This version of KijiSchema continues the maturation process of the KijiSchema framework&#8217;s API. The improvements from the previous version are primarily internal and incremental. Wherever possible, previous functionality has been kept and marked as deprecated rather than removed. Users should see fewer dramatic user-facing alterations than the rc4 release. Further, this will be the final release candidate before the stable 1.0.0 release. Between rc5 and 1.0.0 changes should be limited to critical changes, improving functionality of the DDL shell and CLI, and tidying up the code base.</p>
<p>This release is also synchronized with our first official release of the KijiMR module, which lets users write MapReduce jobs to bulk load and analyze data stored in KijiSchema tables. See the <a href="http://www.kiji.org/2013/03/14/announcing-kijimr/">associated blogpost</a> and <a href="http://docs.kiji.org/userguides/mapreduce/1.0.0-rc5/kiji-mr-overview/">userguide</a> for more information about KijiMR. KijiMR is a younger module and can be expected to undergo a few iterations before its own 1.0.0 release.</p>
<h3>Major new features</h3>
<p>We added several new features to KijiSchema in this version:</p>
<ul>
<li><b>Support for formatted EntityIds (i.e. composite keys of multiple components) in all command line tools</b> has had its coverage improved. Formatted EntityIds were added programmatically in rc4. This change makes such EntityIds usable for all KijiSchema command line tools.</li>
<li><b>Support for formatted EntityIds in the DDL shell</b> has also been added.</li>
<li><b>kiji get and kiji scan</b> have been added, more logically handling functionality which previously existed as part of the <tt>kiji ls</tt> command.</li>
<li><b>kiji ls has changed</b> including gaining the ability to list columns in a table, while the ability to extract data stored in rows has been moved into the <tt>get</tt> and <tt>scan</tt> tools mentioned above.</li>
<li><b>A CLI tool for manipulating the KijiSchema SystemTable</b> has been added. The SystemTable stores instance-wide settings and is now included in metadata backups.</li>
<li><b>CLI tools now accept relative KijiURIs</b> if the user is using <tt>kiji://.env</tt> as their zookeeper quorum. Instance, table, and column names must still be specified. For example, <tt>default/table_foo</tt> is shorthand for <tt>kiji://.env/default/table_foo</tt>.</li>
<li><b>AtomicKijiPutter, providing the ability to apply multiple puts atomically to a single EntityId</b> has been added. Use <tt>table.getWriterFactory().openAtomicWriter()</tt> to obtain one.</li>
</ul>
<p>We made a few API changes that application developers should be aware of:</p>
<ul>
<li><b>New backup format</b> &#8212; The API remains the same, but Metadata backup and its associated commandline tool now also saves information from the SystemTable (containing instance-wide settings) and uses a new format. You should re-backup your tables using the new version of the API.</li>
<li><b>The kiji ls command can no longer perform get and scan</b> &#8212; As mentioned above, new tools <tt>kiji get</tt> and <tt>kiji scan</tt> can be used for reading data stored in KijiSchema tables from scripts and the command<br />
line.</li>
<li><b>KijiDataRequestValidator&#8217;s constructor has been hidden and validate() changed</b> &#8212; Framework developers should use the factory method <tt>validatorForLayout()</tt> to get a validator which can validate KijiDataRequests against a table layout.</li>
<li><b>KijiRowKeySplitter is now a non-static class</b> &#8212; Use <tt>KijiRowKeysplitter.get()</tt> to obtain an instance.</li>
<li><b>KijiRowData.getValues(&#8220;family&#8221;) and .getMostValues(&#8220;family&#8221;) now<br />
only work on map-type column families</b> &#8212; This change is important to be able to return something more expressive than a map of Objects.</li>
<li><b>KijiTable.close() has been deprecated</b> &#8212; Applications should use `KijiTable.release()` instead.</li>
<li><b>Kiji.modifyTableLayout() no longer takes a table name</b> &#8212; Instead, the name is read from the <tt>TableLayoutDesc</tt> parameter. The older version of <tt>modifyTableLayout()</tt> still exists but has been<br />
deprecated.</li>
<li><b>Kiji.createTable() now takes a TableLayoutDesc object</b> &#8212; The older version of <tt>createTable()</tt> that takes a KijiTableLayout still exists but has been deprecated.<br />
<h3>Using new Kiji CLI features</h3>
<p>As mentioned above, the functionality of listing row data has been migrated out of <tt>kiji ls</tt> and into the <tt>get</tt> and <tt>scan</tt> tools. <tt>kiji ls</tt> has also gained the ability to list columns. Here are some example commands using these tools:</p>
<p>List all kiji instances:</p>
<div>
<pre><tt>kiji ls kiji://.env
  kiji ls kiji://localhost:2181
  kiji ls kiji://{host1,host2}:2181
  kiji ls # Relative KijiURI
</tt></pre>
</div>
<p>List all kiji tables in <tt>kiji://.env/default</tt>:</p>
<div>
<pre><tt>kiji ls kiji://.env/default
  kiji ls default # Relative KijiURI
</tt></pre>
</div>
<p>List all columns in a kiji table &#8216;table_foo&#8217;:</p>
<div>
<pre><tt>kiji ls default/table_foo
  kiji ls kiji://.env/default/table_foo
</tt></pre>
</div>
<p>For retrieving data from a single row where one knows the EntityId, use the <tt>kiji get</tt> tool. This commend retrieves displays the columns <tt>info:email</tt> and <tt>derived:domain</tt> from row identified by EntityId &#8220;bar&#8221; in table <tt>table_foo</tt>:</p>
<div>
<pre><tt>kiji get default/table_foo/info:email,derived:domain \
    --entity-id=bar
</tt></pre>
</div>
<p>For getting more than one row, you can use the scan tool. This command scans through up to 10 rows, starting from the first row, and print columns <tt>info:email</tt> and <tt>derived:domain</tt> of table <tt>table_foo</tt>:</p>
<div>
<pre><tt>kiji scan \
    kiji://.env/default/table_foo/info:email,derived:domain \
    --max-rows=10
</tt></pre>
</div>
<p>Scans also support start and limit ranges. This command scans through table <tt>table_foo</tt> form row start-row 0&#215;50 (included) to limit-row 0xe0 (excluded):</p>
<div>
<pre><tt>kiji scan \
    kiji://.env/default/table_foo/info:email,derived:domain \
    --start-row=hex:50 \
    --limit-row=hex:e0
</tt></pre>
</div>
<p>Command line tools will now accept formatted EntityIds for tables whose layout uses them. For example, the following command inserts a value into the <tt>users</tt> table, assuming that the table uses formatted EntityIds consisting of two strings (first and last name in this case):</p>
<div>
<pre><tt>kiji put --target=default/users/info:state --entity-id="[ 'Kimball', 'Aaron' ]" --value='"CA"'
</tt></pre>
</div>
<h3>In summary&#8230;</h3>
<p>KijiSchema&#8217;s rc5 release is an important step in the continued maturation of its functionality and API stabilization. Check back in a few weeks for the stable 1.0.0 release.</p>
<p>Ready to try Kiji? Go <a href="http://www.kiji.org/getstarted">download the BentoBox</a> today!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kiji.org/2013/03/15/announcing-kijischema-1-0-0-rc5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached
Database Caching using memcached
Object Caching 843/1009 objects using memcached
Content Delivery Network via Amazon Web Services: S3: static.kiji.org

 Served from: www.kiji.org @ 2013-05-21 04:14:21 by W3 Total Cache -->