<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>java rants &#187; Technology</title>
	<atom:link href="http://www.javarants.com/category/technology/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.javarants.com</link>
	<description>Rants about Java and other internet technologies by Sam Pullara</description>
	<lastBuildDate>Wed, 21 Jul 2010 17:36:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>HAvroBase: a searchable, evolvable entity store on top of HBase and Solr</title>
		<link>http://www.javarants.com/2010/06/30/havrobase-a-searchable-evolvable-entity-store-on-top-of-hbase-and-solr/</link>
		<comments>http://www.javarants.com/2010/06/30/havrobase-a-searchable-evolvable-entity-store-on-top-of-hbase-and-solr/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 19:55:44 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Startup]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1349</guid>
		<description><![CDATA[Building out a social consumer internet product that could change quickly and evolve over time puts special requirements on the underlying data store. You need to be prepared for scale but not investing too much too early, your business may &#8230; <a href="http://www.javarants.com/2010/06/30/havrobase-a-searchable-evolvable-entity-store-on-top-of-hbase-and-solr/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Building out a social consumer internet product that could change quickly and evolve over time puts special requirements on the underlying data store. You need to be prepared for scale but not investing too much too early, your business may need to pivot in different directions so data models can&#8217;t be set in stone and you need to be able to search that data to enable many of the features users expect from an online social product. I have the additional requirement that I wanted all the entities in the system, regardless of where they are stored, to be accessed the same way and be described by the same data description language for consistency and maintainability. I&#8217;ve created what I think to be a novel solution to these requirements in the form of <a href="http://github.com/spullara/havrobase">HAvroBase</a>.<span id="more-1349"></span></p>
<p>The first choice you have to make against these requirements is which data definition language are you going to use? Instead of depending on the native format of the storage system I&#8217;ve decided to use <a href="http://github.com/apache/avro">Avro</a>. Similar to <a href="http://code.google.com/p/protobuf/">Protocol Buffers</a> and <a href="http://incubator.apache.org/thrift/">Thrift</a>, Avro lets you define your entities using schemas and store them efficiently in a binary format. Additionally, as long as you have the original schema available you can load old data into a new schema. This will let you evolve your stored rows lazily and not have to completely update your storage system when a new field is added or a field is removed.</p>
<p>Whereas the data definition choice is basically commodity at this point and your choice can be somewhat arbitrary, the choice of storage technology will likely be something that has more trade-offs to consider. After looking at the features and communities of a variety of projects including <a href="http://hbase.apache.org/">HBase</a>, <a href="http://cassandra.apache.org/">Cassandra</a>, <a href="http://code.google.com/p/redis/">Redis</a>, <a href="https://wiki.basho.com/display/RIAK/Riak">Riak</a>, <a href="http://mysql.com">MySQL</a>, <a href="http://www.northscale.com/products/membase_server.html">Membase</a>, <a href="http://www.terracotta.org/">Terracotta</a>, etc. I finally chose HBase for a few reasons that may not be that important to you. First I settled on a <a href="http://labs.google.com/papers/bigtable.html">BigTable</a> type choice based on the data model. That left HBase and Cassandra as contenders. There also a few things I think are advantages:</p>
<ul>
<li>multiple tables</li>
<li>better ordered key support</li>
<li>Zookeeper and HDFS were already in my solution</li>
<li>Hive and Hadoop support against the native data format</li>
<li>consistency</li>
<li>compare and set</li>
<li>atomic increment</li>
<li>versioning</li>
</ul>
<p><span style="font-family: Georgia, 'Bitstream Charter', serif; line-height: 24px; font-size: 16px;">Cassandra definitely has its own advantages that didn&#8217;t out-weigh the other considerations including</span></p>
<ul>
<li>performance</li>
<li>simple deployment</li>
<li>always writable</li>
</ul>
<p><span style="font-size: medium;"><span style="line-height: 24px;">You might make different tradeoffs or even use both solutions for different problems. I&#8217;m also biased somewhat as I am sharing an office with <a href="http://cloudera.com/">Cloudera</a> and get top notch support at a moments notice.</span></span></p>
<p><span style="font-size: medium;"><span style="line-height: 24px;">Whether I chose HBase or Cassandra the implementation would have been much the same and with the HAvroBase framework you can have multiple independent storage systems. The framework does somewhat shield you from this decision, at least in your code.</span></span></p>
<p><span style="font-size: medium;"><span style="line-height: 24px;">When it comes to text search you really don&#8217;t get better than <a href="http://lucene.apache.org/">Lucene</a> in open source and the features that <a href="http://wiki.apache.org/solr/FrontPage">Solr</a> builds on top of Lucene make it even better. I don&#8217;t think there is reasonable argument for using something besides Solr at this point. Especially with their support for sharding and replication that comes with <a href="http://wiki.apache.org/solr/SolrCloud">Solr Cloud</a>. It also has the nice benefit that it supports multiple tables, like HBase, so I can efficiently separate entities and allow them to scale independently without managing an additional system.</span></span></p>
<p><span style="font-size: medium;"><span style="line-height: 24px;">The last choice that I made was runtime configuration. There are a few solutions including <a href="http://www.springsource.org/">Spring</a>, <a href="http://code.google.com/p/google-guice/">Guice</a> and rolling my own and I finally landed on the side of Guice. I just like typed, programmatic configuration better than XML files and since that is the focus of Guice, I think it is the best solution for that.</span></span></p>
<p><span style="font-size: medium;"><span style="line-height: 24px;">The first thing that you need to do to use the system is to define an entity in Avro:</span></span><br />
<script src="http://gist.github.com/484813.js"></script><br />
<span style="font-size: small;"><span style="font-size: medium;"><span style="line-height: 24px;">You can use the Avro compiler (or the Maven plugin) to convert that definition to classes (HAvroBase requires this). Then you do the typical things in code to setup your HBase connection but within a Guice module and set some of the configuration parameters for HAB:</span></span></span><br />
<script src="http://gist.github.com/484810.js"></script><br />
<span style="font-size: small;"><span style="font-size: medium;"><span style="line-height: 24px;">That configuration can then be used to instantiate an instance of the HAB class that implements the connection to HBase like this:</span></span></span><br />
<script src="http://gist.github.com/484815.js"></script><br />
<span style="font-size: small;"><span style="font-size: medium;"><span style="line-height: 24px;">You&#8217;ll notice that configuration is somewhat split between things that the base system needs to know and things that the HAB needs to know. For example, what table the schema is store in isn&#8217;t relevant to the base system as an implementer is free to store schemas however they like. But the assumption is that every system will have the concept of a table and a column family in order to separate entities in the underlying storage system. The Solr support is pretty elegant I think. Rather than specifying in more than one place which fields should be indexed, instead at runtime it queries the Solr core&#8217;s schema.xml that defines them and then when you put an entity in the system it automatically indexes those fields.  Here is an example of using some of the APIs:</span></span></span><br />
<script src="http://gist.github.com/484816.js"></script><br />
This example creates a new User, puts it into the HAvroBase, looks it up by row and then searches for it by field that is indexed and finally deletes it. In any fully implemented AvroBase system this should work identically. You&#8217;ll notice in the memcached implementation that only put/get/delete are implemented and it doesn&#8217;t support scan or search at all. I&#8217;ve considered breaking out that functionality into separate interfaces but haven&#8217;t done that yet.</p>
<p>If you are unhappy with the way the default Avro compiler generates code you can use my <a href="http://github.com/spullara/avrocompiler">templated Avro compiler</a> that lets you change the generated code. I have done that for my project to make them a little more developer friendly.</p>
<p>Things left to do:</p>
<ul>
<li>implement guarantees around indexing</li>
<li>optimize schema keys (use an abbrev table instead of a hex sha-256 key)</li>
<li>indexing nested fields and arrays in Solr</li>
</ul>
<p>I&#8217;m sure there are more things left undone but those are some of the more obvious issues.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/06/30/havrobase-a-searchable-evolvable-entity-store-on-top-of-hbase-and-solr/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Static-typing is a powerful metadata database, exploit it!</title>
		<link>http://www.javarants.com/2010/06/16/static-typing-is-a-powerful-metadata-database-exploit-it/</link>
		<comments>http://www.javarants.com/2010/06/16/static-typing-is-a-powerful-metadata-database-exploit-it/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 00:20:47 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1331</guid>
		<description><![CDATA[Today someone decided to pretend they knew something about how a modern statically typed language developer works.  Perhaps they are big emacs fans or something because they felt that static-types leading to autocomplete in an IDE was somehow a feature &#8230; <a href="http://www.javarants.com/2010/06/16/static-typing-is-a-powerful-metadata-database-exploit-it/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Today someone decided to pretend they knew something about how a modern statically typed language developer works.  Perhaps they are big emacs fans or something because they felt that static-types leading to autocomplete in an IDE was somehow a feature in the language FOR THE IDE.  The IDE gets no benefit, in fact, editors like emacs and TextMate are much simpler. But I can tell you that the developer gets a tremendous benefit by having this metadata database not only present in the code and easily queryable but heavily exploited by her tools.  What is amazing about this metadata database is that it is actually populated by that same IDE.  There are very few times that I even type a Type &#8212; 90% of those times are when declaring a new Type &#8212; the rest of the time the IDE is very patiently maintaining and leveraging that database for me.  Even better, when someone else is looking at the source code, or even using the library, they instantly get 80% of the documentation. All that is left are the semantics of the calls. Perhaps we need to have some sort of meetup where we look over each others shoulders and actually understand how someone who is on the other side really works rather than dynamic-typing language people assuming that the programmer is maintaining the huge metadata database present in the static-typing language developers code.  And on the otherside that static-typers are assuming that the dynamic-typing language developer is memorizing all kinds of arcane method call names, argument shapes and the shapes of all the libraries they are using. Do you really memorize all that trivia?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/06/16/static-typing-is-a-powerful-metadata-database-exploit-it/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Building the ideal web application template engine</title>
		<link>http://www.javarants.com/2010/06/16/building-the-ideal-web-application-template-engine/</link>
		<comments>http://www.javarants.com/2010/06/16/building-the-ideal-web-application-template-engine/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 18:02:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1327</guid>
		<description><![CDATA[A month and a half ago I had put out a call for what I was calling the &#8216;ideal web application template engine&#8216; along with a list of requirements that I thought would be present in such a system.  Since &#8230; <a href="http://www.javarants.com/2010/06/16/building-the-ideal-web-application-template-engine/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A month and a half ago I had put out a call for what I was calling the &#8216;<a href="http://www.javarants.com/2010/05/03/the-ideal-web-application-templating-system/">ideal web application template engine</a>&#8216; along with a list of requirements that I thought would be present in such a system.  Since then I looked a bunch of them and decided that I like the simple markup that <a href="http://mustache.github.com/">mustache</a> defined but none of the implementations were up to doing what I wanted.  This led me to embark on building a new engine with for that markup for my chosen platform, Java, which I called creatively, <a href="http://github.com/spullara/mustache.java">mustache.java</a>.  Though it claims to be &#8216;logic-less&#8217; I would say that it has some amount of logic. It will loop over a set of objects and it will check booleans, but I think it is about as close to logic-less as you would want to be in a template language.  So, let&#8217;s look at each of the requirements and how I ended up implementing them:<br />
<span id="more-1327"></span></p>
<ul>
<li><em>Works well with HTML5/CSS3 progressive enhancement</em></li>
</ul>
<p>This one is straight-forward.  Because I put no limitations on the generated text you can actually generate almost anything with mustach.java, in fact, I am using it in another <a href="http://github.com/spullara/avrocompiler">project</a> to generate Java source for Avro objects.  It is really overkill for that project but it is so easy to use that I used it anyway.</p>
<ul>
<li><em>Allows mock data within the template that is replaced at runtime</em></li>
<li><em>Client-side version that leverages the mock data for shift-reload debugging</em></li>
</ul>
<p>These I implemented somewhat differently from the requirement because the mustache template language is not tag based.  I have actually thought about whether it might make sense to make it tag-based and get the full requirement, but I digress.  What I did get to is a system that is easy for a frontend developer or designer to use without having the whole system running on their machine.  Included with mustache.java is a mini-server (called <strong>handlebar</strong>, thanks for the name <a href="http://lukew.com">Luke</a>) that combines mock json data with mustache.java templates. This lets them view a fully rendered version of the page they are working on with the required templating information that will be used in production but without running a big production system. In fact, because mustache.java dynamically generates and compiles Java code, they can fire up <strong>handlebar</strong> in directory along with their mock data and just keep reloading the page to see the effect of changes they make.</p>
<ul>
<li><em> Composable components, not monolithic pages</em></li>
<li><em><em>Very little or no business logic in the templates</em></em></li>
</ul>
<p>The choice of mustache as a base template language ensured that this would be the case.  Including a partial within a template is easy and makes pages very easy to compose. I still miss the Django template style <em>extends/block</em> system and may extend mustache to support it. Having to remember to include things like the header and footer on every page doesn&#8217;t seem necessary.  As I said above, I think that mustache has the minimum reasonable logic.</p>
<ul>
<li><em>Concurrent evaluation possible</em></li>
</ul>
<p>This one was very important to me from a performance perspective. My implementation makes every effort to be as low latency as possible for the end user.  At every possible point in template evaluation things are actually executed in separate threads or purely asynchronously in the case of external I/O like HTTP requests to other services.  The one last thing I am going to do here is to allow not only a straight-line evaluation of the template but the possibility of specifying a timeout so that you can return different markup if evaluation doesn&#8217;t return in time. It may be unnecessary to have this in the base template engine though, still looking at the design of the feature.</p>
<p>So how easy is using the template system?  I think I can answer that question by looking at the relevant portions of the <a href="http://github.com/spullara/mustache.java/blob/master/handlebar/src/main/java/com/sampullara/mustache/Handlebar.java">implementation of </a><strong><a href="http://github.com/spullara/mustache.java/blob/master/handlebar/src/main/java/com/sampullara/mustache/Handlebar.java">handlebar</a>:</strong></p>
<pre>final MustacheCompiler mc = new MustacheCompiler(new File("."));
....
Mustache mustache = mc.compile(new BufferedReader(new FileReader(filename)));
FutureWriter fw = new FutureWriter(res.getWriter());
File file = new File(mocks, base + ".json");
if (file.exists()) {
  BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
  JsonParser parser = jf.createJsonParser(bis);
  JsonNode json = parser.readValueAsTree();
  mustache.execute(fw, new Scope(json));
} else {
  mustache.execute(fw, new Scope());
}
fw.flush();</pre>
<p>The most interesting part of this is the FutureWriter. The future writer lets mustache write evaluated templates completed out of order in template order.  The scope is essentially a sophisticated context object that knows how to pull data from Java objects of various types, including raw object fields and methods, Maps and Json objects. Conveniently, you can also store values in it directly. There are some things I would like to extend at some point, however, for all practical purposes the template system is finished.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/06/16/building-the-ideal-web-application-template-engine/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Android Dalvik VM performance is a threat to the iPhone</title>
		<link>http://www.javarants.com/2010/05/26/android-dalvik-vm-performance-is-a-threat-to-the-iphone/</link>
		<comments>http://www.javarants.com/2010/05/26/android-dalvik-vm-performance-is-a-threat-to-the-iphone/#comments</comments>
		<pubDate>Wed, 26 May 2010 16:29:57 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1311</guid>
		<description><![CDATA[One of the peculiarities of Apple is that they have set themselves down a path where every Apple developer needs to learn Objective-C (and C/C++) to build applications for their platform.  The biggest characteristic of Objective-C vs Java is dynamic &#8230; <a href="http://www.javarants.com/2010/05/26/android-dalvik-vm-performance-is-a-threat-to-the-iphone/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the peculiarities of Apple is that they have set themselves down a path where every Apple developer needs to learn Objective-C (and C/C++) to build applications for their platform.  The biggest characteristic of Objective-C vs Java is dynamic dispatch. At runtime Objective-C can send arbitrary messages to objects and they may or may not respond to them.  This has the nice property that you can write code that is very dynamic and loosely bound but it also has the property that method calls in Objective-C are very slow and the more code that you write in Objective-C instead of in C/C++ the slower your codebase becomes.  Up until Android 2.2 (Froyo) the JVM (really a <a href="http://en.wikipedia.org/wiki/Dalvik_(software)">Dalvik JVM</a> for licensing reasons) on the Android platform was playing with one hand tied behind its back.  Different from desktop/server Java, the JVM was still an interpreter, like the original JVM back in the Java 1.0 days.  It was very efficient interpreter but an interpreter none-the-less and was not creating native code from the Dalvik bytecodes that it uses.  As of Android 2.2 they have added a JIT, a just-in-time compiler, to the stack that translates the Dalvik bytecode into much more efficient machine code much like a C/C++ compiler.  You can see the results of this in the benchmarks of Froyo which <a href="http://crave.cnet.co.uk/mobiles/0,39029453,49305763,00.htm">show a 2-5x improvement</a>.  As they add more and more JIT and GC features that have appeared in HotSpot, JRockit, etc, you will likely see even more improvements over time &#8212; without having to change or recompile the 3rd party developed software.</p>
<p><span id="more-1311"></span></p>
<p>This wouldn&#8217;t be that big a deal if Android software wasn&#8217;t already approaching the speed of the Apple iPhone even when running its applications through the interpreter (see the HTC EVO 4G running 2.1).  This is likely going to mean that 3rd party developer applications created for Android, running on the same hardware, is going to be faster than the same code written against the Objective-C libraries that Apple provides for the iPhone.  You&#8217;ll be able to get more done, have smoother user interfaces and all around build more powerful applications easier.  A better experience for the user and the developer on Android is a bad thing for Apple.</p>
<p>The final issue that Apple has is that far more people know and need  to know Java than Objective-C.  Except for their platform, there is no need to ever learn it.  The tool chain is much more robust, information is much easier to come by, garbage collection is available, and there are thousands more libraries written in Java than Objective-C and far more portable libraries than are written for C/C++.  You might argue that you can always drop down to C/C++ code to make up for the lost performance of using Objective-C (at a significant cost development-wise).  You can do that, except places where you need to make a call into Apple&#8217;s Objective-C runtime libraries or where you want to write callbacks from those libraries. Those are mostly Objective-C libraries and use the dynamic dispatch mechanism which <a href="http://www.javarants.com/2004/05/04/looks-like-apple-should-switch/">I showed in 2004 was very much slower than Java</a>.  I&#8217;d really love to see the whole <a href="http://shootout.alioth.debian.org/">computer language shootout</a> written with Objective-C calling conventions just to show how much slower it is at that level.</p>
<p>Obviously performance is not the only consideration, but it is a big one.  Android has other issues like a fragmented operating system base, hardware feature base and a more complicated user experience.  All those things will conspire to hold it back but I think we can see the writing on the wall that Android is going to dominate iPhone market-share wise which will eventually make it a more attractive platform business-wise.</p>
<p><strong>Update: </strong>Just so people don&#8217;t get the wrong idea, I am a rabid iPhone user and develop for the iPhone first.  This blog entry is to call out a threat that Apple should take seriously.</p>
<p><strong>Update 2: </strong>Alright, you win. Don&#8217;t worry about competing with Google &amp; Android on performance. It probably doesn&#8217;t matter that much for the user experience.  Especially don&#8217;t fix obj_msgSend() with a JIT/LLVM, that would be crazy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/05/26/android-dalvik-vm-performance-is-a-threat-to-the-iphone/feed/</wfw:commentRss>
		<slash:comments>90</slash:comments>
		</item>
		<item>
		<title>Off-loading real work to YQL instead of using your server</title>
		<link>http://www.javarants.com/2010/05/22/off-loading-real-work-to-yql-instead-of-using-your-server/</link>
		<comments>http://www.javarants.com/2010/05/22/off-loading-real-work-to-yql-instead-of-using-your-server/#comments</comments>
		<pubDate>Sun, 23 May 2010 01:23:24 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[yahoo]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1305</guid>
		<description><![CDATA[Just saw a cool blogpost about summing up all your subscribers on RSS, Facebook and Twitter. The only issue is that it requires PHP to work. I decided to quickly rewrite it as a YQL Execute table instead. So rather &#8230; <a href="http://www.javarants.com/2010/05/22/off-loading-real-work-to-yql-instead-of-using-your-server/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Just saw a cool <a href="http://tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/">blogpost about summing up all your subscribers on RSS, Facebook and Twitter</a>.  The only issue is that it requires PHP to work. I decided to quickly rewrite it as a YQL Execute table instead.  So rather than write that code in PHP, here is the <a href="http://javarants.com/yql/stats.xml">code for my table</a>.  Pretty simple. You pass it a URL for Feedburner, an id for Facebook and an id for Twitter and it generates some simple HTML for you to display as a widget.</p>
<p>The html page that he uses didn&#8217;t have to be changed that much, you can find the same demo that he uses <a href="http://javarants.com/subscriberdemo.html">here</a>.  This was really quick so right now there is no way to leave out one without it freaking out.  This is more a tech demo than it is a real solution.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/05/22/off-loading-real-work-to-yql-instead-of-using-your-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maven artifacts need to be more discoverable</title>
		<link>http://www.javarants.com/2010/05/16/maven-artifacts-need-to-be-self-discoverable/</link>
		<comments>http://www.javarants.com/2010/05/16/maven-artifacts-need-to-be-self-discoverable/#comments</comments>
		<pubDate>Mon, 17 May 2010 01:04:17 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1302</guid>
		<description><![CDATA[The laundry list of repositories that are filling the POM in Maven projects has to go. The ideal of having a central store of all artifacts is clearly dead and we have to move on. My proposal is two fold. &#8230; <a href="http://www.javarants.com/2010/05/16/maven-artifacts-need-to-be-self-discoverable/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The laundry list of repositories that are filling the POM in Maven projects has to go.  The ideal of having a central store of all artifacts is clearly dead and we have to move on.  My proposal is two fold.  First, the repository to end all repositories that doesn&#8217;t actually store the files but simply redirects to a known good location for the group id / artifact id / version combination.  The second is that we create an ad hoc standard for artifact discovery based on the group id.  For example, if the group id is com.sampullara.cli-parser then you should be able to find a repository that stores all artifacts at <a href="http://cli-parser.sampullara.com/repository/">http://cli-parser.sampullara.com/repository/</a>.  Perhaps we could even put some sort of discovery file at the root to find them.  This would allow anyone to distribute Maven artifacts to developers without having to publish to any central location.  It would also drastically reduce the amount of repository cruft that is creeping into so many of the POM files I have seen recently.  Further, it would make it really easy for github, googlecode, apache, etc to help their developers automatically publish with just the right naming conventions in place.</p>
<p>Come to think of it, maybe the whole thing is a little suspect.  Maybe we should have been using URLs the entire time.  How much value are we getting out of the layer of indirection?  This is intended to be a discussion&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/05/16/maven-artifacts-need-to-be-self-discoverable/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>How Facebook could open the Open Graph APIs</title>
		<link>http://www.javarants.com/2010/05/12/how-facebook-could-open-the-open-graph-apis/</link>
		<comments>http://www.javarants.com/2010/05/12/how-facebook-could-open-the-open-graph-apis/#comments</comments>
		<pubDate>Wed, 12 May 2010 21:24:31 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1297</guid>
		<description><![CDATA[I was pondering how Facebook could really answer it's critics in a profound way that would really up-level the social fabric of the internet while also satisfying those that want ultimate control over their data. <a href="http://www.javarants.com/2010/05/12/how-facebook-could-open-the-open-graph-apis/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was pondering how Facebook could really answer it&#8217;s critics in a profound way that would really up-level the social fabric of the internet while also satisfying those that want ultimate control over their data.  The basic premise of the solution would be to allow any node in the <a href="http://developers.facebook.com/docs/api">Open Graph</a> to be redirected to a 3rd party developers server.  From that point on, Facebook would then treat that node just as if they were a developer that current gets access to Facebook users.<br />
<span id="more-1297"></span><br />
For example, my URL is currently:</p>
<p><a href="http://graph.facebook.com/2410418">http://graph.facebook.com/2410418</a></p>
<p>If I could easily go to my account and specify a new location for that data, for example, maybe I would put it at:</p>
<p><a href="http://graph.javarants.com/me">http://graph.javarants.com/me</a></p>
<p>Which, for the sake of argument, resolves to much the same information about me, the Sam Pullara node in the graph.  Similarly you could ask for metadata about what other things are available. Since it is a REST API you could mix and match those links to point to different endpoints.  Some of them might point to a new Flickr Open Graph API endpoint that responds with my photos that are available to the caller.  Another might point back at Facebook for my social graph.  While a 3rd could point at a web service (say a new output format for Y! Pipes) that combines my posts on Facebook with my RSS feed and my Twitter feed in order to populate the &#8216;posts&#8217; endpoint.  Using these endpoints Facebook could construct the same set of views they have today on the graph but without being the ultimate authority for the data itself.  Plus, as they would have to call your APIs with the authentication of the viewing part, privacy is under your complete control as well.  For performance reasons, you could still have caching and asynchronous notification systems. Perhaps with some special sauce for websocket you could even allow them to reference the client browser rather than another server for ultimate end user control.</p>
<p>It would be theoretically possible to implement this now without Facebook&#8217;s involvement but without them as one of the providers I don&#8217;t think you could really get the adoption that would make this truly revolutionary.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/05/12/how-facebook-could-open-the-open-graph-apis/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>The ideal web application templating system</title>
		<link>http://www.javarants.com/2010/05/03/the-ideal-web-application-templating-system/</link>
		<comments>http://www.javarants.com/2010/05/03/the-ideal-web-application-templating-system/#comments</comments>
		<pubDate>Mon, 03 May 2010 16:47:05 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1295</guid>
		<description><![CDATA[When a designer and a developer work together to create an HTML web application one of the biggest issues is how you translate their vision into code in a way that allows for iteration and flexibility when those designs change. <a href="http://www.javarants.com/2010/05/03/the-ideal-web-application-templating-system/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>When a designer and a developer work together to create an HTML web application one of the biggest issues is how you translate their vision into code in a way that allows for iteration and flexibility when those designs change.  Another issue is that while you are testing a design you would like it to be filled with actual data but having it hooked up to a live server at all times is very painful.  So far I haven&#8217;t found a system that really gives me even these attributes and as it turns out there are more requirements that I would like that are also mostly unfulfilled.  Here is a list of requirements I would like to see met by a templating system:</p>
<ul>
<li>Works well with HTML5/CSS3 progressive enhancement</li>
<li>Allows mock data within the template that is replaced at runtime</li>
<li>Client-side version that leverages the mock data for shift-reload debugging</li>
<li>Composable components, not monolithic pages</li>
<li>Very little or no business logic in the templates</li>
<li>Concurrent evaluation possible</li>
</ul>
<p>Right now I am looking at <a href="http://github.com/janl/mustache.js/">mustache.js</a> and its various server-side implementations as a possible solution to this.  It has many of those qualities but I would likely need to make some of my own modifications for things like concurrent evaluation.</p>
<p>Any suggestions?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/05/03/the-ideal-web-application-templating-system/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Making Open Data Tables even easier: YQL Storage Editor</title>
		<link>http://www.javarants.com/2010/04/12/making-open-data-tables-even-easier-yql-storage-editor/</link>
		<comments>http://www.javarants.com/2010/04/12/making-open-data-tables-even-easier-yql-storage-editor/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 01:00:22 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[yql]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1274</guid>
		<description><![CDATA[One of the big benefits of YQL is that you can make your own Open Data Tables and use them. However, one of the disadvantages is that you either have to host your tables on a publicly available URL or &#8230; <a href="http://www.javarants.com/2010/04/12/making-open-data-tables-even-easier-yql-storage-editor/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the big benefits of <a href="http://developer.yahoo.com/yql/">YQL</a> is that you can make your own <a href="http://www.datatables.org">Open Data Tables</a> and use them. However, one of the disadvantages is that you either have to host your tables on a publicly available URL or you have to painstakingly use the yql.storage table to manage your environments and table definitions.  There has been an open feature request for the <a href="http://developer.yahoo.com/yql/console/">YQL console</a> for a while now to integrate the ability to edit <a href="http://developer.yahoo.com/yql/console/?_uiFocus=yql">yql.storage</a> content but it isn&#8217;t the highest priority thing for the team right now.  Since I am using YQL more and more lately I decided to build it myself, leveraging <a href="https://bespin.mozillalabs.com/">Bespin</a>, Mozilla&#8217;s web based editor.<br />
<span id="more-1274"></span></p>
<p>Another project that was done in someone&#8217;s free time is <a href="http://zachgrav.es/yql/tablesaw/">Zach Grave&#8217;s TableSaw</a> that helps you generate tables from URLs.  I am going to combine these two things in this post to show you how to make a new table and an environment to more easily use it.  Ultimately I could see TableSaw and the <a href="http://www.javarants.com/yqlstorageeditor/">YQL Storage Editor</a> combined, to that end, I&#8217;ve released the source for this blog post on <a href="http://github.com/spullara/YQL-Storage-Editor">github</a>.</p>
<p>I&#8217;m going to use a real example that I just recently walked through, creating an open data table for the bit.ly API. The table will be pretty simple, just allowing you to pass in a bit.ly link and it will return the long URL for that link.  First thing to do is to go to the <a href="http://code.google.com/p/bitly-api/wiki/ApiDocumentation#/expand">bit.ly API documentation for the expand REST API</a>.  That gives us a nice example URL that we can use in Table Saw to generate a table:</p>
<p><code>http://api.bit.ly/expand?version=2.0.1&#038;shortUrl=http://bit.ly/31IqMl&#038;login=bitlyapidemo&#038;apiKey=R_0da49e0a9118ff35f52f629d2d71bf07</code></p>
<p>If you head over to  Table Saw and put that in the text field and load URL you get:</p>
<div id="attachment_1284" class="wp-caption alignnone" style="width: 615px"><a href="http://www.javarants.com/wp-content/uploads/2010/03/Screen-shot-2010-03-21-at-1.17.13-PM2.png"><img class="size-full wp-image-1284 " title="Table Saw" src="http://www.javarants.com/wp-content/uploads/2010/03/Screen-shot-2010-03-21-at-1.17.13-PM2.png" alt="" width="605" height="819" /></a><p class="wp-caption-text">Initial generated table for api.bit.ly/expand</p></div>
<p>To complete the form and update, fill in an author name and the Produces should be JSON.  One current bug with Table Saw is that it doesn&#8217;t seem to properly remember the Produces field so we will have to edit that after we grab the definition.  Highlight everything under &#8220;Your new YQL Table!&#8221; and copy it into the clipboard and then go to the YQL Storage Editor.  On that page you will see a set of execute/select/update text fields for the various urls that you need to use a yql.storage entry.  Everything is empty right now and we want to create a new one, so click the New button. That should fill in those URL fields with brand new store:// URLs.  Put focus on the Bespin editor component and paste in the table we copied.  If you then click save it should say that it updated the entry in YQL with this new information.  You&#8217;ll notice that there is a text area with the URLs listed out, if you want to keep track of yql.storage entries you need to keep these special identifiers around so you can perform the various operations on the content. I generally have a list that I keep locally of the entries that I am using.  If you paste the list into the file as a comment you can then also just remember the &#8216;select&#8217; URL in order to come back later and find the other two.  Lastly, when the execute key is changed, the two links on the right get updated. The first link goes to the YQL console with your execute key used as an environment and the second link goes to the YQL console with your execute key used as a table definition. These two links can help you quickly try out changes that you make to your environment or table without a lot of cutting and pasting.</p>
<p>Table Saw isn&#8217;t yet perfect, so I make a few edits: change the produces from XML to JSON, add a description, reformat the sample query, set the default version to 2.0.1 and make all the other keys required, this should leave you with a page that looks like:</p>
<div id="attachment_1280" class="wp-caption alignnone" style="width: 680px"><a href="http://www.javarants.com/wp-content/uploads/2010/03/Screen-shot-2010-03-21-at-1.31.14-PM1.png"><img class="size-full wp-image-1280 " title="YQL Storage Editor" src="http://www.javarants.com/wp-content/uploads/2010/03/Screen-shot-2010-03-21-at-1.31.14-PM1.png" alt="" width="670" height="670" /></a><p class="wp-caption-text">Edited version of the bit.ly table</p></div>
<p>When you click save it should alert you that it was saved successfully by saying that it was updated.  You can now test this table in the YQL console with the following query:</p>
<p><code>use 'store://8tLqFvgCm8kdOAp60lPz24' as bit.ly; select * from bit.ly where version='2.0.1' and shortUrl='http://bit.ly/31IqMl' and login='bitlyapidemo' and apiKey='R_0da49e0a9118ff35f52f629d2d71bf07'</code></p>
<p>I noticed at this point that I forgot the itemPath and then set it to &#8220;json.results&#8221; in order to cut out the error messages and some other things that I wasn&#8217;t interested in.  Nagesh Susarla had a great blog post on using YQL storage for secrets.  We&#8217;ll also do that by using the YQL storage editor to create a new environment for us to use that could store our secret values that bit.ly needs in order to run the API. Create another YQL Storage Editor tab, click New and then we can make an environment that uses the table, sets the login and sets the API key:</p>
<div id="attachment_1279" class="wp-caption alignnone" style="width: 527px"><a href="http://www.javarants.com/wp-content/uploads/2010/03/Screen-shot-2010-03-21-at-1.41.26-PM.png"><img class="size-full wp-image-1279" title="bit.ly environment" src="http://www.javarants.com/wp-content/uploads/2010/03/Screen-shot-2010-03-21-at-1.41.26-PM.png" alt="The bit.ly default environment with their internal API keys" width="517" height="227" /></a><p class="wp-caption-text">Secret bit.ly environment with their API keys</p></div>
<p>Now using that execute URL as your env value in your query URLs you can have very simple queries against this API.  For example, if you use this <a href="http://developer.yahoo.com/yql/console/?env=store://TZ0z8H3V1vSOQGE2pLxDzm&#038;_uiFocus=bit">URL for the YQL Console</a> you can use this much simpler query that gets all its authentication implicitly:</p>
<p><code>select * from bit.ly where shortUrl='http://bit.ly/31IqMl'</code></p>
<p>This allows you to not embed those valuable keys directly in your client software or even in your source control system but hidden behind what amounts to a very secure random password.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/04/12/making-open-data-tables-even-easier-yql-storage-editor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Coders At Work Interview</title>
		<link>http://www.javarants.com/2010/03/11/coders-at-work-interview/</link>
		<comments>http://www.javarants.com/2010/03/11/coders-at-work-interview/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 23:24:25 +0000</pubDate>
		<dc:creator>Sam Pullara</dc:creator>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.javarants.com/?p=1263</guid>
		<description><![CDATA[Peter Seibel wrote a great book called Coders at Work which contains interviews of various programmers throughout computer science history. Yury Lifshits has put up a site called Interview 2010 that lets you both define interviews and respond to them. &#8230; <a href="http://www.javarants.com/2010/03/11/coders-at-work-interview/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.gigamonkeys.com">Peter Seibel</a> wrote a great book called <a href="http://codersatwork.com">Coders at Work</a> which contains interviews of various programmers throughout computer science history.  Yury Lifshits has put up a site called <a href="http://interview2010.com">Interview 2010 </a>that lets you both define interviews and respond to them.  Peter graciously agreed to put up a <a href="http://coders.interview2010.com">subset of his questions</a> for the interviews that he did and I have my answers below.  After that, you will find a form to enter your own answers to this set of questions.</p>
<style type="text/css">
    p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 24.0px; font: 24.0px Lucida Grande; color: #83053f}
    p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 24.0px; font: 16.0px Lucida Grande; color: #222222}
    p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 24.0px; font: 16.0px Lucida Grande; color: #222222; min-height: 18.0px}
    span.s1 {font: 16.0px Lucida Grande; color: #222222}
</style>
<p class="p1">Sam Pullara</p>
<p class="p2">Long-time computer programmer</p>
<p class="p2"><b>Peter Seibel:</b> How did you learn to program?</p>
<p class="p2"><b>Sam Pullara:</b> Back when I was around 10 I asked for a computer. My mother looked at the available choices and decided that the Atari 400 was just a game machine and the VIC-20 looked like I might actually learn something. She was right. I started out programming in BASIC and then later 6502 machine code on the 64 and 128. In high school I finally learned a &#8216;real&#8217; computer programming language, C, by reading a 700 page volume book in a single night. One day I will take a computer class.</p>
<p><span id="more-1263"></span></p>
<p class="p2"><b>Peter Seibel:</b> What is the thing that you worked on that you are most proud of?</p>
<p class="p2"><b>Sam Pullara:</b> The work that I did helping to create the WebLogic Server. Building a system that thousands of developers and in turn millions of users depended on was a great experience and very challenging. Ultimately, that work was acquired not by one company but eventually by two and is still one of the best enterprise software servers on the market in the very capable hands of Oracle.</p>
<p class="p2"><b>Peter Seibel:</b> What about books? Are there particular computer science or programming books that everyone should read?</p>
<p class="p2"><b>Sam Pullara:</b> I haven&#8217;t read a great deal of computer science books though I enjoy books about algorithms, languages and patterns rather than books about the details of programming an API or in a certain domain.</p>
<p class="p2"><b>Peter Seibel:</b> Do you still read code for fun, as opposed to reading it because you need to work with it?</p>
<p class="p2"><b>Sam Pullara:</b> I love exploring a new piece of code. Digging into something deeply and seeing the nuances and edge cases the developer discovered as they created the program is very interesting to me. I&#8217;ve had to hand my code off many times in my career and I am always pleased when someone takes the care to create code that is easily understood rather than clever.</p>
<p class="p2"><b>Peter Seibel:</b> What about organization, do you organize your code top down or bottom up? Do you refactor to keep the internal structure of the code coherent? Or do you have just very good sense at the beginning?</p>
<p class="p2"><b>Sam Pullara:</b> I try to write code that always works and refactor it into the final design. Java and its IDEs have trained me to write code backwards in many cases with the structure flowing out of an initially very procedural constructs. The invention of isomorphic transformations on code and semantic code completion have completely slaved me to languages that conform to the restrictions that make those very things possible.</p>
<p class="p2"><b>Peter Seibel:</b> How do you go about debugging?</p>
<p class="p2"><b>Sam Pullara:</b> I use a mixture of Zen, printlns and actual debuggers depending on the circumstances. For very esoteric edge conditions I prefer to figure out what must be true and work backwards from there. When code is only badly behaved rarely, printlns help you discover where you should look or think about. For complicated algorithms, I do enjoy the occasional debugging session where you interrogate every line to see if it is behaving as you expect.</p>
<p class="p2"><b>Peter Seibel:</b> How do you tackle understanding a piece of code that you didn&#8217;t write?</p>
<p class="p2"><b>Sam Pullara:</b> Figure out an interesting feature to add to it and add it. Nothing lets you really understand a piece of code like trying to change it. The tools of the trade are typically a refactoring IDE with all the modern bits of introspection that you can bring to bear. I&#8217;ve found that even obfuscated code is east to understand with modern tooling.</p>
<p class="p2"><b>Peter Seibel:</b> What about the length and intensity? I am sure you&#8217;ve done 80-, 100-, 120-hour weeks. Is that necessary? Under what circumstances it is really necessary and when it is just macho thing to do?</p>
<p class="p2"><b>Sam Pullara:</b> I have a pattern where I think and think and think, tinker, tinker, think and then finally in a like one huge breath blow the program out of my mind and into the computer. That final breath can take hours and hours straight but it is so much better than trying to force it before it is time.</p>
<h2>Here is the form for your own answers to these questions:</h2>
<div style="padding: 9px 9px 9px 9px; font-family: Lucida Grande, Tahoma, Arial, sans-serif; line-height:1.5em; color:#222;  margin: 0; ">
<div>
<form method="post" action="http://coders.interview2010.com/give/" ><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">Your full name or nickname</span><br />
<input id="id_name" style="width: 250px;  margin-bottom: 8px; border:2px solid #ddd;" type="text" name="name" maxlength="30" />
<p><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">Couple of words about yourself</span><br />
<input id="id_occupation" style="width: 250px;  margin-bottom: 8px; border:2px solid #ddd;" type="text" name="occupation" maxlength="200" />
<p><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">How did you learn to program?</span><br /><textarea id="id_a0" style="border:2px solid #ddd; margin-bottom: 8px; width:100%; height:80px;" rows="5" cols="40" name="a0"></textarea><br /><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">What is the thing that you worked on that you are most proud of?</span><br /><textarea id="id_a1" style="border:2px solid #ddd; margin-bottom: 8px; width:100%; height:80px;" rows="5" cols="40" name="a1"></textarea><br /><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">What about books? Are there particular computer science or programming books that everyone should read?</span><br /><textarea id="id_a2" style="border:2px solid #ddd; margin-bottom: 8px; width:100%; height:80px;" rows="5" cols="40" name="a2"></textarea><br /><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">Do you still read code for fun, as opposed to reading it because you need to work with it?</span><br /><textarea id="id_a3" style="border:2px solid #ddd; margin-bottom: 8px; width:100%; height:80px;" rows="5" cols="40" name="a3"></textarea><br /><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">What about organization, do you organize your code top down or bottom up? Do you refactor to keep the internal structure of the code coherent? Or do you have just very good sense at the beginning?</span><br /><textarea id="id_a4" style="border:2px solid #ddd; margin-bottom: 8px; width:100%; height:80px;" rows="5" cols="40" name="a4"></textarea><br /><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">How do you go about debugging?</span><br /><textarea id="id_a5" style="border:2px solid #ddd; margin-bottom: 8px; width:100%; height:80px;" rows="5" cols="40" name="a5"></textarea><br /><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">How do you tackle understanding a piece of code that you didn&#39;t write?</span><br /><textarea id="id_a6" style="border:2px solid #ddd; margin-bottom: 8px; width:100%; height:80px;" rows="5" cols="40" name="a6"></textarea><br /><span style="margin:15px 0px 5px 0px; color:#333; font-size:14px;">What about the length and intensity? I am sure you&#39;ve done 80-, 100-, 120-hour weeks. Is that necessary? Under what circumstances it is really necessary and when it is just macho thing to do?</span><br /><textarea id="id_a7" style="border:2px solid #ddd; margin-bottom: 8px; width:100%; height:80px;" rows="5" cols="40" name="a7"></textarea><br />
<input type="submit" style="width: auto; padding:5px; cursor: pointer; cursor: hand;" value="Publish your answers"></form>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.javarants.com/2010/03/11/coders-at-work-interview/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
