I followed the wiki documentation to deploy. It seems it needs to be updated with specific versions (and anything else if needed). Also, I am curious - shouldn't the deploy script check versions then?
________________________________________ From: Ignasi Barrera [ignasi.barr...@gmail.com] Sent: Friday, September 05, 2014 2:56 AM To: dev@jclouds.apache.org Subject: Re: svn commit: r1622496 [1/4] - in /jclouds/site-content: ./ blog/ blog/2009/05/13/catching-exceptions-with-less-keystrokes/ blog/2011/10/18/jclouds-1-2-released/ blog/2012/03/23/take-a-peek-at-vcloud-director-1-5-openstack-and/ blog/2012/05/02/new-to... I think it is due to the version of Jekyll. Our Jenkins uses Jekyll 1.5.1, and it renders a bit different than older versions (IIRC). We should definitely better document that. For the next time, there are two options: * Install Jekyll 1.5.1 and force the version when generating the site as explained here [1]. * Carefully read the script prompt with the changes that are going to be committed and just commit the ones that are relevant and discard the rest. [1] https://github.com/jclouds/jclouds-site/blob/master/deploy-site.sh#L3-L9 On 4 September 2014 18:35, Zack Shoylev <zack.shoy...@rackspace.com> wrote: > AFAIK latest versions of both. Anything broken? > ________________________________________ > From: Ignasi Barrera [ignasi.barr...@gmail.com] > Sent: Thursday, September 04, 2014 11:29 AM > To: dev@jclouds.apache.org > Subject: Re: svn commit: r1622496 [1/4] - in /jclouds/site-content: ./ blog/ > blog/2009/05/13/catching-exceptions-with-less-keystrokes/ > blog/2011/10/18/jclouds-1-2-released/ > blog/2012/03/23/take-a-peek-at-vcloud-director-1-5-openstack-and/ > blog/2012/05/02/new-to... > > Zach wichi version of Jekyll were you using? Did you use the latest > version of the script to generate the site? > > I'm just wondering, why the commit for your blog post modified all those > files. > > In any case, that can be prevented by taking a look at the script > output (which should prompt you) and manually adding *only* the > relevant files if needed, and discard the rest? > > > > On 4 September 2014 17:18, <zac...@apache.org> wrote: >> Author: zachsh >> Date: Thu Sep 4 15:18:35 2014 >> New Revision: 1622496 >> >> URL: http://svn.apache.org/r1622496 >> Log: >> deploy jclouds site content >> >> Added: >> jclouds/site-content/blog/2014/09/ >> jclouds/site-content/blog/2014/09/03/ >> jclouds/site-content/blog/2014/09/03/better-builders/ >> jclouds/site-content/blog/2014/09/03/better-builders/index.html >> Modified: >> >> jclouds/site-content/blog/2009/05/13/catching-exceptions-with-less-keystrokes/index.html >> jclouds/site-content/blog/2011/10/18/jclouds-1-2-released/index.html >> >> jclouds/site-content/blog/2012/03/23/take-a-peek-at-vcloud-director-1-5-openstack-and/index.html >> jclouds/site-content/blog/2012/05/02/new-toys-in-1-5-0-alpha-6/index.html >> >> jclouds/site-content/blog/2012/07/16/fluency-for-paginated-api-lists/index.html >> >> jclouds/site-content/blog/2012/12/12/jclouds-1-5-4-mistletoe-released/index.html >> jclouds/site-content/blog/atom.xml >> jclouds/site-content/blog/index.html >> jclouds/site-content/blog/page2/index.html >> jclouds/site-content/blog/page3/index.html >> jclouds/site-content/blog/page4/index.html >> jclouds/site-content/blog/page5/index.html >> jclouds/site-content/guides/abiquo-cloud/index.html >> jclouds/site-content/guides/abiquo/index.html >> jclouds/site-content/guides/aws-ebs/index.html >> jclouds/site-content/guides/aws-ec2/index.html >> jclouds/site-content/guides/aws-sqs/index.html >> jclouds/site-content/guides/aws/index.html >> jclouds/site-content/guides/azure-storage/index.html >> jclouds/site-content/guides/bluelock/index.html >> jclouds/site-content/guides/chef/index.html >> jclouds/site-content/guides/cloudsigma/index.html >> jclouds/site-content/guides/docker/index.html >> jclouds/site-content/guides/filesystem/index.html >> jclouds/site-content/guides/glacier/index.html >> jclouds/site-content/guides/go-grid/index.html >> jclouds/site-content/guides/hpcloud/index.html >> jclouds/site-content/guides/karaf/index.html >> jclouds/site-content/guides/openstack/index.html >> jclouds/site-content/guides/rackspace/index.html >> jclouds/site-content/guides/vcloud-director/index.html >> jclouds/site-content/guides/vcloud/index.html >> jclouds/site-content/index.html >> jclouds/site-content/reference/configuration/index.html >> jclouds/site-content/reference/logging/index.html >> jclouds/site-content/reference/troubleshooting/index.html >> jclouds/site-content/releasenotes/1.1.0/index.html >> jclouds/site-content/releasenotes/1.2/index.html >> jclouds/site-content/releasenotes/1.6.1/index.html >> jclouds/site-content/releasenotes/1.6.2/index.html >> jclouds/site-content/releasenotes/1.6.3/index.html >> jclouds/site-content/releasenotes/1.7.0/index.html >> jclouds/site-content/releasenotes/1.7.1/index.html >> jclouds/site-content/releasenotes/1.7.2/index.html >> jclouds/site-content/releasenotes/1.7.3/index.html >> jclouds/site-content/releasenotes/atom.xml >> jclouds/site-content/start/blobstore/index.html >> jclouds/site-content/start/compute/index.html >> jclouds/site-content/start/install/index.html >> >> Modified: >> jclouds/site-content/blog/2009/05/13/catching-exceptions-with-less-keystrokes/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/2009/05/13/catching-exceptions-with-less-keystrokes/index.html?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- >> jclouds/site-content/blog/2009/05/13/catching-exceptions-with-less-keystrokes/index.html >> (original) >> +++ >> jclouds/site-content/blog/2009/05/13/catching-exceptions-with-less-keystrokes/index.html >> Thu Sep 4 15:18:35 2014 >> @@ -154,8 +154,7 @@ >> <span class="o">}</span> <span class="k">catch</span> <span >> class="o">(</span><span class="n">Exception</span> <span >> class="n">e</span><span class="o">)</span> <span class="o">{</span> >> <span class="n">Utils</span><span class="o">.<</span><span >> class="n">ApplicationException</span><span class="o">></span><span >> class="n">rethrowIfRuntimeOrSameType</span><span class="o">(</span><span >> class="n">e</span><span class="o">);</span> >> <span class="k">throw</span> <span class="k">new</span> <span >> class="nf">ApplicationException</span><span class="o">(</span><span >> class="s">"Error applying stuff"</span><span class="o">,</span> >> <span class="n">e</span><span class="o">);</span> >> -<span class="o">}</span> >> -</code></pre></div> >> +<span class="o">}</span></code></pre></div> >> >> >> <p>This code does what it says, preventing us from unnecessarily nesting >> application exceptions or swallowing runtimes.</p> >> @@ -170,8 +169,7 @@ >> <span class="o">}</span> <span class="k">catch</span> <span >> class="o">(</span><span class="n">ClassCastException</span> <span >> class="n">throwAway</span><span class="o">)</span> <span class="o">{</span> >> <span class="c1">// using cce as there's no way to do >> instanceof E in current java</span> >> <span class="o">}</span> >> -<span class="o">}</span> >> -</code></pre></div> >> +<span class="o">}</span></code></pre></div> >> >> >> <p>The trick is that we try to force the exception we caught into the >> generic type. If that fails, we know it wasn't that type and that we should >> wrap, log, etc.</p> >> >> Modified: >> jclouds/site-content/blog/2011/10/18/jclouds-1-2-released/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/2011/10/18/jclouds-1-2-released/index.html?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- jclouds/site-content/blog/2011/10/18/jclouds-1-2-released/index.html >> (original) >> +++ jclouds/site-content/blog/2011/10/18/jclouds-1-2-released/index.html Thu >> Sep 4 15:18:35 2014 >> @@ -158,8 +158,7 @@ >> >> <div class="highlight"><pre><code class="java"><span >> class="n">future</span> <span class="o">=</span> <span >> class="n">client</span><span class="o">.</span><span >> class="na">submitScriptOnNode</span><span class="o">(</span><span >> class="n">node</span><span class="o">.</span><span >> class="na">getId</span><span class="o">(),</span> >> <span class="n">AdminAccess</span><span >> class="o">.</span><span class="na">builder</span><span >> class="o">().</span><span class="na">adminUsername</span><span >> class="o">(</span><span class="s">"foo"</span><span >> class="o">).</span><span class="na">build</span><span class="o">(),</span> >> - <span class="n">nameTask</span><span >> class="o">(</span><span class="s">"adminUpdate"</span><span >> class="o">));</span> >> -</code></pre></div> >> + <span class="n">nameTask</span><span >> class="o">(</span><span class="s">"adminUpdate"</span><span >> class="o">));</span></code></pre></div> >> >> >> <p>As always, we keep our <a >> href="https://github.com/jclouds/jclouds-examples">examples site</a> up to >> date so you can see how to work this stuff. Next release will be in >> approximately 1-months time. Look out for progress including <a >> href="http://www.vmware.com/products/vcloud-director/overview.html">vCloud >> 1.5</a>, <a href="http://voxel.net/voxcloud">Voxel</a>, and <a >> href="https://www.virtualbox.org/">VirtualBox</a>.</p> >> >> Modified: >> jclouds/site-content/blog/2012/03/23/take-a-peek-at-vcloud-director-1-5-openstack-and/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/2012/03/23/take-a-peek-at-vcloud-director-1-5-openstack-and/index.html?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- >> jclouds/site-content/blog/2012/03/23/take-a-peek-at-vcloud-director-1-5-openstack-and/index.html >> (original) >> +++ >> jclouds/site-content/blog/2012/03/23/take-a-peek-at-vcloud-director-1-5-openstack-and/index.html >> Thu Sep 4 15:18:35 2014 >> @@ -162,14 +162,12 @@ >> <div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="nf">use</span> <span >> class="o">'</span><span class="ss">'org.jclouds.compute2</span><span >> class="p">)</span> >> <span class="p">(</span><span class="nb">import </span><span >> class="o">'</span><span >> class="ss">'org.jclouds.scriptbuilder.statements.login.AdminAccess</span><span >> class="p">)</span> >> <span class="p">(</span><span class="k">def </span><span >> class="nv">compute</span> <span class="p">(</span><span >> class="nf">compute-service</span> <span >> class="s">"hpcloud-compute"</span> <span >> class="s">"tenantId:ACCESSKEY"</span> <span >> class="s">"SECRETKEY"</span> <span class="ss">:slf4j</span> >> <span class="ss">:sshj</span><span class="p">))</span> >> -<span class="p">(</span><span class="nf">create-node</span> <span >> class="nv">compute</span> <span class="s">"test"</span> <span >> class="p">(</span><span class="nf">build-template</span> <span >> class="nv">compute</span> <span class="p">{</span> <span >> class="ss">:run-script</span> <span class="p">(</span><span >> class="nf">AdminAccess/standard</span><span class="p">)</span> <span >> class="p">}</span> <span class="p">))</span> >> -</code></pre></div> >> +<span class="p">(</span><span class="nf">create-node</span> <span >> class="nv">compute</span> <span class="s">"test"</span> <span >> class="p">(</span><span class="nf">build-template</span> <span >> class="nv">compute</span> <span class="p">{</span> <span >> class="ss">:run-script</span> <span class="p">(</span><span >> class="nf">AdminAccess/standard</span><span class="p">)</span> <span >> class="p">}</span> <span class="p">))</span></code></pre></div> >> >> >> <p>Here's an example of how to do the same on <a >> href="https://trystack.org/">TryStack</a>, authenticating w/ user & pass >> as opposed to key, via our <a >> href="https://github.com/jclouds/jclouds-examples/tree/master/compute-basics">java >> example</a>:</p> >> >> -<div class="highlight"><pre><code class="bash">java -jar >> target/compute-basics-jar-with-dependencies.jar trystack-nova tenantId:user >> password mygroup add >> -</code></pre></div> >> +<div class="highlight"><pre><code class="bash">java -jar >> target/compute-basics-jar-with-dependencies.jar trystack-nova tenantId:user >> password mygroup add</code></pre></div> >> >> >> <p>In the group org.jclouds.labs, you'll find two more new and notable >> members of the jclouds family:</p> >> @@ -182,8 +180,7 @@ >> >> <p>You can try out virtualbox like any other api. For example, you can use >> the clojure above, only changing how you create the connection slightly:</p> >> >> -<div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="k">def </span><span class="nv">compute</span> >> <span class="p">(</span><span class="nf">compute-service</span> <span >> class="s">"virtualbox"</span> <span >> class="s">"administrator"</span> <span >> class="s">"12345"</span> <span class="ss">:sshj</span> <span >> class="ss">:slf4j</span><span class="p">))</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="k">def </span><span class="nv">compute</span> >> <span class="p">(</span><span class="nf">compute-service</span> <span >> class="s">"virtualbox"</span> <span >> class="s">"administrator"</span> <span >> class="s">"12345"</span> <span class="ss">:sshj</span> <span >> class="ss">:slf4j</span><span class="p">))</span></code></pre></div> >> >> >> <p>The code in labs will certainly change before we release a beta, but >> feel free to check them out. Meanwhile, you can try them out and give us >> feedback on #jclouds irc freenode or jclouds-dev google group!</p> >> @@ -192,8 +189,7 @@ >> >> <p>Oh, and don't forget to clean up your nodes :)</p> >> >> -<div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="nf">destroy-nodes-matching</span> <span >> class="nv">compute</span> <span class="p">(</span><span >> class="nb">constantly </span><span class="nv">true</span><span >> class="p">))</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="nf">destroy-nodes-matching</span> <span >> class="nv">compute</span> <span class="p">(</span><span >> class="nb">constantly </span><span class="nv">true</span><span >> class="p">))</span></code></pre></div> >> >> >> >> >> Modified: >> jclouds/site-content/blog/2012/05/02/new-toys-in-1-5-0-alpha-6/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/2012/05/02/new-toys-in-1-5-0-alpha-6/index.html?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- >> jclouds/site-content/blog/2012/05/02/new-toys-in-1-5-0-alpha-6/index.html >> (original) >> +++ >> jclouds/site-content/blog/2012/05/02/new-toys-in-1-5-0-alpha-6/index.html >> Thu Sep 4 15:18:35 2014 >> @@ -161,8 +161,7 @@ >> <span class="k">for</span> <span class="o">(</span><span >> class="n">Tenant</span> <span class="n">tenant</span> <span >> class="o">:</span> <span class="n">adminClient</span><span >> class="o">.</span><span class="na">listTenants</span><span >> class="o">())</span> <span class="o">{</span> >> <span class="c1">// ...</span> >> <span class="o">}</span> >> -<span class="o">}</span> >> -</code></pre></div> >> +<span class="o">}</span></code></pre></div> >> >> >> <p>Also pro, is our new Amazon CloudWatch support from Jeremy Whitlock. >> This is our first complete renovation of an AWS api to have the same >> look/feel as our new OpenStack stuff. Just add a dependency on >> <em>org.jclouds.providers/aws-cloudwatch</em> and you can do this!</p> >> @@ -177,8 +176,7 @@ >> <span class="k">for</span> <span class="o">(</span><span >> class="n">Metric</span> <span class="n">metric</span> <span >> class="o">:</span> <span class="n">metricClient</span><span >> class="o">.</span><span class="na">listMetrics</span><span >> class="o">())</span> <span class="o">{</span> >> <span class="c1">// ...</span> >> <span class="o">}</span> >> -<span class="o">}</span> >> -</code></pre></div> >> +<span class="o">}</span></code></pre></div> >> >> >> <p>And for the jenkins users, we also have an api for remote job and >> computer control, at <em>org.jclouds.labs/jenkins</em>!</p> >> @@ -187,8 +185,7 @@ >> <span class="n">RestContext</span> <span class="n">localhost</span> <span >> class="o">=</span> <span class="n">contextBuilder</span><span >> class="o">.</span><span class="na">build</span><span class="o">();</span> >> >> <span class="n">Node</span> <span class="n">master</span> <span >> class="o">=</span> <span class="n">localhost</span><span >> class="o">.</span><span class="na">getApi</span><span >> class="o">().</span><span class="na">getMaster</span><span >> class="o">();</span> >> -<span class="n">localhost</span><span class="o">.</span><span >> class="na">getJobClient</span><span class="o">().</span><span >> class="na">createFromXML</span><span class="o">(</span><span >> class="s">"newJob"</span><span class="o">,</span> <span >> class="n">xmlAsString</span><span class="o">);</span> >> -</code></pre></div> >> +<span class="n">localhost</span><span class="o">.</span><span >> class="na">getJobClient</span><span class="o">().</span><span >> class="na">createFromXML</span><span class="o">(</span><span >> class="s">"newJob"</span><span class="o">,</span> <span >> class="n">xmlAsString</span><span class="o">);</span></code></pre></div> >> >> >> <p>This is especially helpful with the new <a >> href="https://github.com/jenkinsci/jclouds-plugin">jclouds-plugin</a>, which >> uses jclouds to spin up new slaves and publish artifacts to BlobStore. Tons >> more in there, too.</p> >> >> Modified: >> jclouds/site-content/blog/2012/07/16/fluency-for-paginated-api-lists/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/2012/07/16/fluency-for-paginated-api-lists/index.html?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- >> jclouds/site-content/blog/2012/07/16/fluency-for-paginated-api-lists/index.html >> (original) >> +++ >> jclouds/site-content/blog/2012/07/16/fluency-for-paginated-api-lists/index.html >> Thu Sep 4 15:18:35 2014 >> @@ -168,8 +168,7 @@ >> >> <h3>Lazy advance through all your metrics:</h3> >> >> -<div class="highlight"><pre><code class="java"><span >> class="n">FluentIterable</span><span class="o"><</span><span >> class="n">Metric</span><span class="o">></span> <span >> class="n">allMetrics</span> <span class="o">=</span> <span >> class="n">cloudwatch</span><span class="o">.</span><span >> class="na">getMetricApi</span><span class="o">().</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">concat</span><span class="o">();</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="java"><span >> class="n">FluentIterable</span><span class="o"><</span><span >> class="n">Metric</span><span class="o">></span> <span >> class="n">allMetrics</span> <span class="o">=</span> <span >> class="n">cloudwatch</span><span class="o">.</span><span >> class="na">getMetricApi</span><span class="o">().</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">concat</span><span class="o">();</span></code></pre></div> >> >> >> <h3>Â Advance only until we find the load balancer we want:</h3> >> @@ -177,14 +176,12 @@ >> <div class="highlight"><pre><code class="java"><span >> class="n">Optional</span><span class="o"><</span><span >> class="n">LoadBalancer</span><span class="o">></span> <span >> class="n">firstInterestingLoadBalancer</span> <span class="o">=</span> <span >> class="n">elb</span> >> <span class="o">.</span><span class="na">getLoadBalancerApi</span><span >> class="o">().</span><span class="na">list</span><span class="o">()</span> >> <span class="o">.</span><span class="na">concat</span><span >> class="o">()</span> >> - <span class="o">.</span><span class="na">firstMatch</span><span >> class="o">(</span><span class="n">isInterestingLB</span><span >> class="o">());</span> >> -</code></pre></div> >> + <span class="o">.</span><span class="na">firstMatch</span><span >> class="o">(</span><span class="n">isInterestingLB</span><span >> class="o">());</span></code></pre></div> >> >> >> <h3>Get only the first page of database instances</h3> >> >> -<div class="highlight"><pre><code class="java"><span >> class="n">IterableWithMarker</span><span class="o"><</span><span >> class="n">Instance</span><span class="o">></span> <span >> class="n">firstPage</span> <span class="o">=</span> <span >> class="n">rds</span><span class="o">.</span><span >> class="na">getInstanceApi</span><span class="o">().</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">get</span><span class="o">(</span><span class="mi">0</span><span >> class="o">);</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="java"><span >> class="n">IterableWithMarker</span><span class="o"><</span><span >> class="n">Instance</span><span class="o">></span> <span >> class="n">firstPage</span> <span class="o">=</span> <span >> class="n">rds</span><span class="o">.</span><span >> class="na">getInstanceApi</span><span class="o">().</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">get</span><span class="o">(</span><span class="mi">0</span><span >> class="o">);</span></code></pre></div> >> >> >> <p>The above syntax is being worked through relevant apis. In order to try >> it out, grab jclouds 1.5.0-beta.7 (releasing today), and use any of the >> following methods:</p> >> >> Modified: >> jclouds/site-content/blog/2012/12/12/jclouds-1-5-4-mistletoe-released/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/2012/12/12/jclouds-1-5-4-mistletoe-released/index.html?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- >> jclouds/site-content/blog/2012/12/12/jclouds-1-5-4-mistletoe-released/index.html >> (original) >> +++ >> jclouds/site-content/blog/2012/12/12/jclouds-1-5-4-mistletoe-released/index.html >> Thu Sep 4 15:18:35 2014 >> @@ -156,8 +156,7 @@ >> >> <p>For example, the following syntax can be used in karaf directly, or via >> the <a href="https://github.com/jclouds/jclouds-cli">jclouds cli</a> to >> start a node in any supported cloud and bootstrap chef recipes.</p> >> >> -<div class="highlight"><pre><code class="bash">karaf@root>node-create >> --adminAccess --recipe chef/java::openjdk karaf >> -</code></pre></div> >> +<div class="highlight"><pre><code class="bash">karaf@root>node-create >> --adminAccess --recipe chef/java::openjdk karaf</code></pre></div> >> >> >> <h2>What else is in 1.5.4?</h2> >> @@ -168,16 +167,14 @@ >> >> <p><a href="https://github.com/everett-toews">Everett</a> modernized >> support for <strong>rackspace-cloudloadbalancers-us</strong> and >> <strong>uk</strong> is now available. This includes syntactic sugar such as >> auto-pagination and easy transforms.</p> >> >> -<div class="highlight"><pre><code class="java"><span >> class="n">FluentIterable</span><span class="o"><</span><span >> class="n">HostAndPort</span><span class="o">></span> <span >> class="n">sockets</span> <span class="o">=</span> <span >> class="n">clb</span><span class="o">.</span><span >> class="na">getLoadBalancerApiForZone</span><span class="o">(</span><span >> class="n">zone</span><span class="o">).</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">concat</span><span class="o">().</span><span >> class="na">transform</span><span class="o">(</span><span >> class="n">converter</span><span class="o">);</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="java"><span >> class="n">FluentIterable</span><span class="o"><</span><span >> class="n">HostAndPort</span><span class="o">></span> <span >> class="n">sockets</span> <span class="o">=</span> <span >> class="n">clb</span><span class="o">.</span><span >> class="na">getLoadBalancerApiForZone</span><span class="o">(</span><span >> class="n">zone</span><span class="o">).</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">concat</span><span class="o">().</span><span >> class="na">transform</span><span class="o">(</span><span >> class="n">converter</span><span class="o">);</span></code></pre></div> >> >> >> <h3>Nova Server Diagnostics</h3> >> >> <p>Some implementations of Nova have diagnostic information available. >> Thanks to <a href="https://github.com/LeanderBB">Leander</a>, you can now >> discover this capability at runtime.</p> >> >> -<div class="highlight"><pre><code class="java"><span >> class="n">Optional</span><span class="o"><</span><span >> class="n">Map</span><span class="o">></span> <span >> class="n">diagnosticInfo</span> <span class="o">=</span> <span >> class="n">novaApi</span><span class="o">.</span><span >> class="na">getServerApiForZone</span><span class="o">(</span><span >> class="s">"az-1.region-a.geo-1"</span><span >> class="o">).</span><span class="na">getDiagnostics</span><span >> class="o">(</span><span class="n">serverId</span><span class="o">);</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="java"><span >> class="n">Optional</span><span class="o"><</span><span >> class="n">Map</span><span class="o">></span> <span >> class="n">diagnosticInfo</span> <span class="o">=</span> <span >> class="n">novaApi</span><span class="o">.</span><span >> class="na">getServerApiForZone</span><span class="o">(</span><span >> class="s">"az-1.region-a.geo-1"</span><span >> class="o">).</span><span class="na">getDiagnostics</span><span >> class="o">(</span><span class="n">serverId</span><span >> class="o">);</span></code></pre></div> >> >> >> <h3>S3 Multi-Object delete</h3> >> @@ -185,8 +182,7 @@ >> <p><a href="http://maginatics.com/">Maginatics</a> have BlobStore >> containers with over a billion objects in them. S3 containers (buckets) can >> now be cleared with 1/1000 the requests, thanks to <a >> href="https://twitter.com/andreisavu">Andrei</a>'s additional support of S3 >> multi-delete.</p> >> >> <div class="highlight"><pre><code class="java"><span >> class="n">DeleteResult</span> <span class="n">result</span> <span >> class="o">=</span> <span class="n">s3Api</span><span class="o">.</span><span >> class="na">deleteObjects</span><span class="o">(</span><span >> class="n">container</span><span class="o">,</span> <span >> class="n">keys</span><span class="o">);</span> >> -<span class="n">assertEquals</span><span class="o">(</span><span >> class="n">result</span><span class="o">.</span><span >> class="na">size</span><span class="o">(),</span> <span >> class="n">keys</span><span class="o">.</span><span >> class="na">size</span><span class="o">());</span> >> -</code></pre></div> >> +<span class="n">assertEquals</span><span class="o">(</span><span >> class="n">result</span><span class="o">.</span><span >> class="na">size</span><span class="o">(),</span> <span >> class="n">keys</span><span class="o">.</span><span >> class="na">size</span><span class="o">());</span></code></pre></div> >> >> >> <h2>What's next</h2> >> >> Added: jclouds/site-content/blog/2014/09/03/better-builders/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/2014/09/03/better-builders/index.html?rev=1622496&view=auto >> ============================================================================== >> --- jclouds/site-content/blog/2014/09/03/better-builders/index.html (added) >> +++ jclouds/site-content/blog/2014/09/03/better-builders/index.html Thu Sep >> 4 15:18:35 2014 >> @@ -0,0 +1,344 @@ >> +<!DOCTYPE html> >> +<html lang="en"> >> + <head> >> + <meta charset="utf-8"> >> +<title>Apache jclouds® :: Better Builders with jclouds!</title> >> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> >> +<meta name="description" content=""> >> +<meta name="author" content=""> >> + >> +<!--link rel="stylesheet/less" href="less/bootstrap.less" type="text/css" >> /--> >> +<!--link rel="stylesheet/less" href="less/responsive.less" type="text/css" >> /--> >> +<!--script src="js/less-1.3.3.min.js"></script--> >> +<!--append â?~#!watchâ?T to the browser URL, then refresh the page. --> >> + >> +<link href="/css/bootstrap.min.css" rel="stylesheet"> >> +<link href="/css/style.css" rel="stylesheet"> >> +<link href="/css/syntax.css" rel="stylesheet"> >> + >> +<!-- HTML5 shim, for IE6-8 support of HTML5 elements --> >> +<!--[if lt IE 9]> >> +<script src="js/html5shiv.js"></script> >> +<![endif]--> >> + >> +<!-- Fav and touch icons --> >> +<!-- >> +<link rel="apple-touch-icon-precomposed" sizes="144x144" >> href="/img/apple-touch-icon-144-precomposed.png"> >> +<link rel="apple-touch-icon-precomposed" sizes="114x114" >> href="/img/apple-touch-icon-114-precomposed.png"> >> +<link rel="apple-touch-icon-precomposed" sizes="72x72" >> href="/img/apple-touch-icon-72-precomposed.png"> >> +<link rel="apple-touch-icon-precomposed" >> href="/img/apple-touch-icon-57-precomposed.png"> >> +--> >> +<link rel="shortcut icon" href="/favicon.ico"> >> + >> +<link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" >> title="Blog Posts Feed"> >> +<link rel="alternate" type="application/atom+xml" >> href="/releasenotes/atom.xml" title="Release Notes Feed"> >> + >> +<script type="text/javascript" src="/js/jquery.min.js"></script> >> +<script type="text/javascript" src="/js/bootstrap.min.js"></script> >> +<script type="text/javascript" src="/js/toc.js"></script> >> + >> +<script type="text/javascript"> >> + var _gaq = _gaq || []; >> + _gaq.push(['_setAccount', 'UA-8638379-1']); >> + _gaq.push(['_trackPageview']); >> + >> + (function() { >> + var ga = document.createElement('script'); ga.type = >> 'text/javascript'; ga.async = true; >> + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : >> 'http://www') + '.google-analytics.com/ga.js'; >> + var s = document.getElementsByTagName('script')[0]; >> s.parentNode.insertBefore(ga, s); >> + })(); >> +</script> >> +<script type="text/javascript"> >> + >> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ >> + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new >> Date();a=s.createElement(o), >> + >> m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) >> + >> })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); >> + >> + ga('create', 'UA-47106724-1', 'jclouds.apache.org'); >> + ga('send', 'pageview'); >> +</script> >> + >> + </head> >> + <body> >> + <nav class="navbar navbar-default navbar-fixed-top" >> role="navigation"> >> + <div class="container"> >> + <div class="navbar-header"> >> + <button type="button" class="navbar-toggle" >> data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> >> + <span class="sr-only">Toggle navigation</span> >> + <span class="icon-bar"></span> >> + <span class="icon-bar"></span> >> + <span class="icon-bar"></span> >> + </button> >> + <a class="navbar-brand" href="/">Apache jclouds ®</a> >> + </div> >> + >> + <div class="collapse navbar-collapse" >> id="bs-example-navbar-collapse-1"> >> + <ul class="nav navbar-nav"> >> + <li class="dropdown"> >> + <a href="#" class="dropdown-toggle" >> data-toggle="dropdown">Getting Started<strong class="caret"></strong></a> >> + <ul class="dropdown-menu"> >> + <li><a href="/start/what-is-jclouds/">What Is >> Apache jclouds?</a></li> >> + <li><a href="/start/install/">Installation >> Guide</a></li> >> + <li class="divider"></li> >> + <li><a href="/start/concepts/">Core >> Concepts</a></li> >> + <li><a >> href="/start/compute/">ComputeService</a></li> >> + <li><a href="/start/blobstore/">BlobStore</a></li> >> + <li><a >> href="http://github.com/jclouds/jclouds-examples">Examples</a></li> >> + </ul> >> + </li> >> + <li class="dropdown"> >> + <a href="#" class="dropdown-toggle" >> data-toggle="dropdown">Documentation<strong class="caret"></strong></a> >> + <ul class="dropdown-menu"> >> + <li><a href="/reference/providers/">Cloud >> Providers</a></li> >> + <li><a href="/guides">User Guides</a></li> >> + <li><a >> href="/reference/troubleshooting/">Troubleshooting</a></li> >> + <li><a >> href="/reference/configuration/">Configuration</a></li> >> + <li><a href="/reference/logging/">Logging</a></li> >> + <li><a href="/reference/javadoc/">Javadoc</a></li> >> + <li class="divider"></li> >> + <li class="dropdown-header">Developer Guides</li> >> + <li><a >> href="http://wiki.apache.org/jclouds/">Wiki</a></li> >> + </ul> >> + </li> >> + <li class="dropdown"> >> + <a href="#" class="dropdown-toggle" >> data-toggle="dropdown">Community<strong class="caret"></strong></a> >> + <ul class="dropdown-menu"> >> + <li><a href="/community/">Get In Touch!</a></li> >> + <li><a href="http://www.meetup.com/jclouds/">Attend >> An Event</a></li> >> + <li><a href="/community/users/">Who Is Using >> jclouds?</a></li> >> + <li class="divider"></li> >> + <li class="dropdown-header">Contribute</li> >> + <li><a href="/reference/report-a-bug/">Report a >> Bug</a></li> >> + <li><a >> href="http://wiki.apache.org/jclouds/How%20to%20Contribute">How To >> Contribute Code</a></li> >> + <li><a >> href="http://wiki.apache.org/jclouds/How%20to%20Contribute%20Documentation">How >> To Contribute Documentation</a></li> >> + </ul> >> + </li> >> + <li><a href="/blog">Blog</a></li> >> + </ul> >> + <ul class="nav navbar-nav navbar-right"> >> + <li class="dropdown"> >> + <a href="#" class="dropdown-toggle" >> data-toggle="dropdown">Release Notes<strong class="caret"></strong></a> >> + <ul class="dropdown-menu"> >> + <!-- only keep the release notes for supported >> versions in this list --> >> + <li><a href="/releasenotes/1.8.0">1.8.0</a></li> >> + <li><a href="/releasenotes/1.7.3">1.7.3</a></li> >> + <li><a href="/releasenotes/1.7.2">1.7.2</a></li> >> + <li><a href="/releasenotes/1.7.1">1.7.1</a></li> >> + <li><a href="/releasenotes/1.7.0">1.7.0</a></li> >> + <li class="divider"></li> >> + <li class="dropdown-header">Previous releases</li> >> + <li><a href="/releasenotes">Release archive</a></li> >> + </ul> >> + </li> >> + <li> >> + <div> >> + <a class="btn btn-success navbar-btn" >> href="/start/install/"> >> + <span class="glyphicon >> glyphicon-download"></span> >> + Install >> + </a> >> + </div> >> + </li> >> + </ul> >> + </div> >> + </div> >> +</nav> >> + >> + <div class="container"> >> + <div class="page-header"> >> + <h1>Better Builders with jclouds!</h1> >> + <span class="text-muted">03 September 2014, by Zack >> Shoylev</span> >> + </div> >> + <p>If you are a new <a href="jclouds.apache.org">jclouds</a> >> developer, or even if you are already developing jclouds support for any of >> the OpenStack or Rackspace APIs, you have likely seen the domain classes >> that are used throughout the the jclouds codebase. >> +These classes are used to represent OpenStack resources, particularly the >> JSON structures supported by OpenStack APIs.</p> >> + >> +<!--more--> >> + >> + >> +<p>For example, when listing database users in openstack-trove (the >> OpenStack database API), the service returns a JSON response body describing >> the existing users. This JSON might look something like this:</p> >> + >> +<div class="highlight"><pre><code class="json"><span class="p">{</span> >> + <span class="nt">"users"</span><span class="p">:</span> <span >> class="p">[</span> >> + <span class="p">{</span> >> + <span class="nt">"databases"</span><span >> class="p">:</span> <span class="p">[],</span> >> + <span class="nt">"host"</span><span >> class="p">:</span> <span class="s2">"%"</span><span >> class="p">,</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"dbuser1"</span> >> + <span class="p">},</span> >> + <span class="p">{</span> >> + <span class="nt">"databases"</span><span >> class="p">:</span> <span class="p">[</span> >> + <span class="p">{</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"databaseB"</span> >> + <span class="p">},</span> >> + <span class="p">{</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"databaseC"</span> >> + <span class="p">}</span> >> + <span class="p">],</span> >> + <span class="nt">"host"</span><span >> class="p">:</span> <span class="s2">"%"</span><span >> class="p">,</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"dbuser2"</span> >> + <span class="p">},</span> >> + <span class="p">{</span> >> + <span class="nt">"databases"</span><span >> class="p">:</span> <span class="p">[],</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"dbuser3"</span><span >> class="p">,</span> >> + <span class="nt">"host"</span><span >> class="p">:</span> <span class="s2">"%"</span> >> + <span class="p">},</span> >> + <span class="p">{</span> >> + <span class="nt">"databases"</span><span >> class="p">:</span> <span class="p">[</span> >> + <span class="p">{</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"sampledb"</span> >> + <span class="p">}</span> >> + <span class="p">],</span> >> + <span class="nt">"host"</span><span >> class="p">:</span> <span class="s2">"%"</span><span >> class="p">,</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"demouser"</span> >> + <span class="p">}</span> >> + <span class="p">]</span> >> +<span class="p">}</span></code></pre></div> >> + >> + >> +<p>To parse the response, jclouds uses <a >> href="https://github.com/jclouds/jclouds/blob/master/apis/openstack-trove/src/main/java/org/jclouds/openstack/trove/v1/domain/User.java">domain >> classes</a> to represent the JSON data returned by the service. The array >> of "users" is unwrapped into individual User domain objects. Conversely, >> when creating users, domain objects are transformed into a JSON request >> body.</p> >> + >> +<p>Because of the relative simplicity of user creation in trove, jclouds >> developers can use a create method in the features package without having to >> build an instance of the User class. For example, the developer might use a >> method such as</p> >> + >> +<div class="highlight"><pre><code class="java"><span >> class="kt">boolean</span> <span class="nf">create</span><span >> class="o">(</span><span class="n">String</span> <span >> class="n">userName</span><span class="o">,</span> <span >> class="n">String</span> <span class="n">password</span><span >> class="o">,</span> <span class="n">String</span> <span >> class="n">databaseName</span><span class="o">);</span></code></pre></div> >> + >> + >> +<p>In this case, it was easy to add support for this call by using a <a >> href="https://github.com/jclouds/jclouds/blob/master/apis/openstack-trove/src/main/java/org/jclouds/openstack/trove/v1/binders/BindCreateUserToJson.java">map >> binder</a>.</p> >> + >> +<p>However, some APIs send or receive significantly more complex JSON >> structures. Recent work on Neutron has shown that there are benefits to >> increased consistency among the domain classes and the OpenStack API calls >> that use them.</p> >> + >> +<p>Current implementations have the following two issues :</p> >> + >> +<ol> >> +<li>Heavy use of map-binders and parsers to transform JSON. Map-binders use >> annotation-selected classes to map method data (such as the data in the >> create-user call above) to the JSON required by the service. The <a >> href="https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2_0/functions/ParseNetworkDetails.java">parsers</a> >> apply the reverse transformation: from JSON to domain objects.</li> >> +<li>Lack of consistent, concise, and user-friendly way to use domain >> objects in create/update/list methods.</li> >> +</ol> >> + >> + >> +<p>In addition to fixing these issues, jclouds wants to provide developers >> with some compiler checks and other syntactic sugar (fluent builders), while >> also supporting different updating, creating, or listing validation >> strategies.</p> >> + >> +<p>We want to</p> >> + >> +<ol> >> +<li>Ensure object immutability.</li> >> +<li>Utilize the fluent builder pattern.</li> >> +<li>Ensure that "create" objects can only be used for create; update for >> update; and listed resources cannot be directly sent back to the >> service.</li> >> +<li>Reuse code and keep domain classes <a >> href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a>.</li> >> +<li>Allow using different validation strategies (for example, create vs >> update).</li> >> +</ol> >> + >> + >> +<p>We have been able to identify a pattern that addresses these issues. >> Here is some <a >> href="https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Router.java">sample >> code</a>.</p> >> + >> +<p>This approach reuses code by having <a >> href="https://code.google.com/p/google-gson/">GSON</a> handle the domain >> objects directly, as much as possible, both for serialization and >> deserialization, thus eliminating map-binders and parsers in most cases. The >> domain classes annotate their member variables using the @Named (for >> serialization) and @ConstructorProperties (for deserialization) >> annotations.</p> >> + >> +<p>Many of the JSON attributes in Neutron are optional. GSON's jclouds >> configuration supports such optional values by using @Nullable and boxed >> types. An alternate supported method, more convoluted, implements >> Optional<T> private member variables and getter return types.</p> >> + >> +<p>To ensure immutability, users have no access to a constructor or >> setters, and instead they must instantiate domain objects by using a >> slightly modified Builder pattern. The builder pattern also provides proper >> validation and user-friendliness.</p> >> + >> +<p>Some <a >> href="https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/AddressPair.java">simpler >> classes</a> implement the regular fluent builder pattern.</p> >> + >> +<p>In <a >> href="https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/NetworkApi.java">other >> cases</a>, the same domain class has several different purposes, such as >> making sure users have different Network-subtype object instances for >> updating, creating, and listing networks:</p> >> + >> +<ol> >> +<li>Listing networks returns a Network or a list of Networks.</li> >> +<li>Updating a network requires Network.UpdateOptions.</li> >> +<li>Creating a network requires Network.CreateOptions.</li> >> +</ol> >> + >> + >> +<p>CreateOptions and UpdateOptions extend Network and implement their own >> copy constructors, with custom validation, if needed.</p> >> + >> +<p>To instantiate these create or update-specific objects, developers have >> access to CreateBuilder and UpdateBuilder, which both extend the regular >> Network builder abstract class. The only code these special builders >> implement: the constructor (taking as parameters any required properties), a >> build() method returning the create or update object, and also self(). The >> self method is needed to make sure we can reuse most of the Builder code, >> but still be able to chain the fluent builder methods.</p> >> + >> +<p>This is how it all works out from the developer's perspective:</p> >> + >> +<div class="highlight"><pre><code class="java"><span >> class="n">Network</span><span class="o">.</span><span >> class="na">CreateOptions</span> <span class="n">createNetwork</span> <span >> class="o">=</span> <span class="n">Network</span><span >> class="o">.</span><span class="na">createOptions</span><span >> class="o">(</span><span class="s">"jclouds-wibble"</span><span >> class="o">)</span> >> + <span class="o">.</span><span class="na">networkType</span><span >> class="o">(</span><span class="n">NetworkType</span><span >> class="o">.</span><span class="na">LOCAL</span><span class="o">)</span> >> + <span class="o">.</span><span class="na">build</span><span >> class="o">();</span> >> + >> +<span class="n">Network</span> <span class="n">network</span> <span >> class="o">=</span> <span class="n">networkApi</span><span >> class="o">.</span><span class="na">create</span><span >> class="o">(</span><span class="n">createNetwork</span><span >> class="o">);</span> >> + >> +<span class="n">Network</span><span class="o">.</span><span >> class="na">UpdateOptions</span> <span class="n">updateNetwork</span> <span >> class="o">=</span> <span class="n">Network</span><span >> class="o">.</span><span class="na">updateOptions</span><span >> class="o">()</span> >> + <span class="o">.</span><span class="na">name</span><span >> class="o">(</span><span >> class="s">"jclouds-wibble-updated"</span><span class="o">)</span> >> + <span class="o">.</span><span class="na">networkType</span><span >> class="o">(</span><span class="n">NetworkType</span><span >> class="o">.</span><span class="na">LOCAL</span><span class="o">)</span> >> + <span class="o">.</span><span class="na">build</span><span >> class="o">();</span> >> + >> +<span class="n">networkApi</span><span class="o">.</span><span >> class="na">update</span><span class="o">(</span><span class="s">"some >> id"</span><span class="o">,</span> <span >> class="n">updateNetwork</span><span class="o">);</span></code></pre></div> >> + >> + >> +<p>This ensures developers get an easy to understand interface, with >> validation and compiler checks. It also allows jclouds developers to use >> significantly less code when developing complex domain classes that need to >> be reused in list/create/update API calls.</p> >> + >> + >> + <div id="comments"> >> + <hr/> >> + <div id="disqus_thread"></div> >> +<script type="text/javascript"> >> +var disqus_shortname = 'jclouds'; >> +/* * * DON'T EDIT BELOW THIS LINE * * */ >> +(function() { >> + var dsq = document.createElement('script'); dsq.type = >> 'text/javascript'; dsq.async = true; >> + dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; >> + (document.getElementsByTagName('head')[0] || >> document.getElementsByTagName('body')[0]).appendChild(dsq); >> +})(); >> +</script> >> +<noscript>Please enable JavaScript to view the <a >> href="http://disqus.com/?ref_noscript">Comments powered by >> Disqus.</a></noscript> >> +<a href="http://disqus.com" class="dsq-brlink">Comments powered by <span >> class="logo-disqus">Disqus</span></a> >> + >> + </div> >> + >> + <div class="row clearfix"> >> + <div id="footer" class="col-md-12 column"> >> + <div id="footer"> >> + <hr/> >> + <div class="row clearfix"> >> + <div class="col-md-2 column"> >> + <p class="text-center"> >> + <a class="text-primary" href="/start/">Getting Started</a> >> + </p> >> + </div> >> + <div class="col-md-2 column"> >> + <p class="text-center"> >> + <a class="text-primary" >> href="/reference/report-a-bug/">Report a Bug</a> >> + </p> >> + </div> >> + <div class="col-md-2 column"> >> + <p class="text-center"> >> + <a >> href="https://github.com/jclouds/jclouds-site/edit/master/_posts/2014-09-03-better-builders.md">Fix >> This Page</a><a class="text-primary" >> href="https://wiki.apache.org/jclouds/How%20to%20Contribute%20Documentation"><sup>*</sup></a> >> + </p> >> + </div> >> + <div class="col-md-2 column"> >> + <p class="text-center"> >> + <a class="text-primary" >> href="https://wiki.apache.org/jclouds/How%20to%20Contribute">Contribute >> Code</a> >> + </p> >> + </div> >> + <div class="col-md-2 column"> >> + <p class="text-center"> >> + <a class="text-primary" href="/community/">Contact Us</a> >> + </p> >> + </div> >> + <div class="col-md-2 column"> >> + <p class="text-center"> >> + <a class="text-primary" >> href="https://twitter.com/jclouds">Follow Us</a> >> + </p> >> + </div> >> + </div> >> + <hr style="margin-top: 10px"/> >> + <div class="row clearfix"> >> + <div class="col-md-12 column"> >> + <p class="text-center"> >> + Copyright © 2011-2014 <a >> href="http://www.apache.org">The Apache Software Foundation</a>. All Rights >> Reserved. >> + </p> >> + <p class="text-center"> >> + Apache, jclouds, Apache jclouds, the jclouds logo, and the >> Apache feather logos are registered trademarks or trademarks of the Apache >> Software Foundation. >> + </p> >> + <p class="text-center"> >> + <img src="/img/feather-small.gif" width="80", height="24"/> >> + </p> >> + <br/> >> + </div> >> + </div> >> +</div> >> + >> + </div> >> + </div> >> + </div> >> + </body> >> +</html> >> >> Modified: jclouds/site-content/blog/atom.xml >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/atom.xml?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- jclouds/site-content/blog/atom.xml (original) >> +++ jclouds/site-content/blog/atom.xml Thu Sep 4 15:18:35 2014 >> @@ -8,6 +8,131 @@ >> >> >> <entry> >> + <id>http://jclouds.apache.org/blog/2014/09/03/better-builders</id> >> + <title type="html"><![CDATA[Better Builders with jclouds!]]></title> >> + <link href="http://jclouds.apache.org/blog/2014/09/03/better-builders"/> >> + <updated>2014-09-03T00:00:00Z</updated> >> + <content type="html"><![CDATA[<p>If you are a new <a >> href="jclouds.apache.org">jclouds</a> developer, or even if you are already >> developing jclouds support for any of the OpenStack or Rackspace APIs, you >> have likely seen the domain classes that are used throughout the the jclouds >> codebase. >> +These classes are used to represent OpenStack resources, particularly the >> JSON structures supported by OpenStack APIs.</p> >> + >> +<!--more--> >> + >> + >> +<p>For example, when listing database users in openstack-trove (the >> OpenStack database API), the service returns a JSON response body describing >> the existing users. This JSON might look something like this:</p> >> + >> +<div class="highlight"><pre><code class="json"><span class="p">{</span> >> + <span class="nt">"users"</span><span class="p">:</span> <span >> class="p">[</span> >> + <span class="p">{</span> >> + <span class="nt">"databases"</span><span >> class="p">:</span> <span class="p">[],</span> >> + <span class="nt">"host"</span><span >> class="p">:</span> <span class="s2">"%"</span><span >> class="p">,</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"dbuser1"</span> >> + <span class="p">},</span> >> + <span class="p">{</span> >> + <span class="nt">"databases"</span><span >> class="p">:</span> <span class="p">[</span> >> + <span class="p">{</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"databaseB"</span> >> + <span class="p">},</span> >> + <span class="p">{</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"databaseC"</span> >> + <span class="p">}</span> >> + <span class="p">],</span> >> + <span class="nt">"host"</span><span >> class="p">:</span> <span class="s2">"%"</span><span >> class="p">,</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"dbuser2"</span> >> + <span class="p">},</span> >> + <span class="p">{</span> >> + <span class="nt">"databases"</span><span >> class="p">:</span> <span class="p">[],</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"dbuser3"</span><span >> class="p">,</span> >> + <span class="nt">"host"</span><span >> class="p">:</span> <span class="s2">"%"</span> >> + <span class="p">},</span> >> + <span class="p">{</span> >> + <span class="nt">"databases"</span><span >> class="p">:</span> <span class="p">[</span> >> + <span class="p">{</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"sampledb"</span> >> + <span class="p">}</span> >> + <span class="p">],</span> >> + <span class="nt">"host"</span><span >> class="p">:</span> <span class="s2">"%"</span><span >> class="p">,</span> >> + <span class="nt">"name"</span><span >> class="p">:</span> <span class="s2">"demouser"</span> >> + <span class="p">}</span> >> + <span class="p">]</span> >> +<span class="p">}</span></code></pre></div> >> + >> + >> +<p>To parse the response, jclouds uses <a >> href="https://github.com/jclouds/jclouds/blob/master/apis/openstack-trove/src/main/java/org/jclouds/openstack/trove/v1/domain/User.java">domain >> classes</a> to represent the JSON data returned by the service. The array >> of "users" is unwrapped into individual User domain objects. Conversely, >> when creating users, domain objects are transformed into a JSON request >> body.</p> >> + >> +<p>Because of the relative simplicity of user creation in trove, jclouds >> developers can use a create method in the features package without having to >> build an instance of the User class. For example, the developer might use a >> method such as</p> >> + >> +<div class="highlight"><pre><code class="java"><span >> class="kt">boolean</span> <span class="nf">create</span><span >> class="o">(</span><span class="n">String</span> <span >> class="n">userName</span><span class="o">,</span> <span >> class="n">String</span> <span class="n">password</span><span >> class="o">,</span> <span class="n">String</span> <span >> class="n">databaseName</span><span class="o">);</span></code></pre></div> >> + >> + >> +<p>In this case, it was easy to add support for this call by using a <a >> href="https://github.com/jclouds/jclouds/blob/master/apis/openstack-trove/src/main/java/org/jclouds/openstack/trove/v1/binders/BindCreateUserToJson.java">map >> binder</a>.</p> >> + >> +<p>However, some APIs send or receive significantly more complex JSON >> structures. Recent work on Neutron has shown that there are benefits to >> increased consistency among the domain classes and the OpenStack API calls >> that use them.</p> >> + >> +<p>Current implementations have the following two issues :</p> >> + >> +<ol> >> +<li>Heavy use of map-binders and parsers to transform JSON. Map-binders use >> annotation-selected classes to map method data (such as the data in the >> create-user call above) to the JSON required by the service. The <a >> href="https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2_0/functions/ParseNetworkDetails.java">parsers</a> >> apply the reverse transformation: from JSON to domain objects.</li> >> +<li>Lack of consistent, concise, and user-friendly way to use domain >> objects in create/update/list methods.</li> >> +</ol> >> + >> + >> +<p>In addition to fixing these issues, jclouds wants to provide developers >> with some compiler checks and other syntactic sugar (fluent builders), while >> also supporting different updating, creating, or listing validation >> strategies.</p> >> + >> +<p>We want to</p> >> + >> +<ol> >> +<li>Ensure object immutability.</li> >> +<li>Utilize the fluent builder pattern.</li> >> +<li>Ensure that "create" objects can only be used for create; update for >> update; and listed resources cannot be directly sent back to the >> service.</li> >> +<li>Reuse code and keep domain classes <a >> href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a>.</li> >> +<li>Allow using different validation strategies (for example, create vs >> update).</li> >> +</ol> >> + >> + >> +<p>We have been able to identify a pattern that addresses these issues. >> Here is some <a >> href="https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Router.java">sample >> code</a>.</p> >> + >> +<p>This approach reuses code by having <a >> href="https://code.google.com/p/google-gson/">GSON</a> handle the domain >> objects directly, as much as possible, both for serialization and >> deserialization, thus eliminating map-binders and parsers in most cases. The >> domain classes annotate their member variables using the @Named (for >> serialization) and @ConstructorProperties (for deserialization) >> annotations.</p> >> + >> +<p>Many of the JSON attributes in Neutron are optional. GSON's jclouds >> configuration supports such optional values by using @Nullable and boxed >> types. An alternate supported method, more convoluted, implements >> Optional<T> private member variables and getter return types.</p> >> + >> +<p>To ensure immutability, users have no access to a constructor or >> setters, and instead they must instantiate domain objects by using a >> slightly modified Builder pattern. The builder pattern also provides proper >> validation and user-friendliness.</p> >> + >> +<p>Some <a >> href="https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/AddressPair.java">simpler >> classes</a> implement the regular fluent builder pattern.</p> >> + >> +<p>In <a >> href="https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/NetworkApi.java">other >> cases</a>, the same domain class has several different purposes, such as >> making sure users have different Network-subtype object instances for >> updating, creating, and listing networks:</p> >> + >> +<ol> >> +<li>Listing networks returns a Network or a list of Networks.</li> >> +<li>Updating a network requires Network.UpdateOptions.</li> >> +<li>Creating a network requires Network.CreateOptions.</li> >> +</ol> >> + >> + >> +<p>CreateOptions and UpdateOptions extend Network and implement their own >> copy constructors, with custom validation, if needed.</p> >> + >> +<p>To instantiate these create or update-specific objects, developers have >> access to CreateBuilder and UpdateBuilder, which both extend the regular >> Network builder abstract class. The only code these special builders >> implement: the constructor (taking as parameters any required properties), a >> build() method returning the create or update object, and also self(). The >> self method is needed to make sure we can reuse most of the Builder code, >> but still be able to chain the fluent builder methods.</p> >> + >> +<p>This is how it all works out from the developer's perspective:</p> >> + >> +<div class="highlight"><pre><code class="java"><span >> class="n">Network</span><span class="o">.</span><span >> class="na">CreateOptions</span> <span class="n">createNetwork</span> <span >> class="o">=</span> <span class="n">Network</span><span >> class="o">.</span><span class="na">createOptions</span><span >> class="o">(</span><span class="s">"jclouds-wibble"</span><span >> class="o">)</span> >> + <span class="o">.</span><span class="na">networkType</span><span >> class="o">(</span><span class="n">NetworkType</span><span >> class="o">.</span><span class="na">LOCAL</span><span class="o">)</span> >> + <span class="o">.</span><span class="na">build</span><span >> class="o">();</span> >> + >> +<span class="n">Network</span> <span class="n">network</span> <span >> class="o">=</span> <span class="n">networkApi</span><span >> class="o">.</span><span class="na">create</span><span >> class="o">(</span><span class="n">createNetwork</span><span >> class="o">);</span> >> + >> +<span class="n">Network</span><span class="o">.</span><span >> class="na">UpdateOptions</span> <span class="n">updateNetwork</span> <span >> class="o">=</span> <span class="n">Network</span><span >> class="o">.</span><span class="na">updateOptions</span><span >> class="o">()</span> >> + <span class="o">.</span><span class="na">name</span><span >> class="o">(</span><span >> class="s">"jclouds-wibble-updated"</span><span class="o">)</span> >> + <span class="o">.</span><span class="na">networkType</span><span >> class="o">(</span><span class="n">NetworkType</span><span >> class="o">.</span><span class="na">LOCAL</span><span class="o">)</span> >> + <span class="o">.</span><span class="na">build</span><span >> class="o">();</span> >> + >> +<span class="n">networkApi</span><span class="o">.</span><span >> class="na">update</span><span class="o">(</span><span class="s">"some >> id"</span><span class="o">,</span> <span >> class="n">updateNetwork</span><span class="o">);</span></code></pre></div> >> + >> + >> +<p>This ensures developers get an easy to understand interface, with >> validation and compiler checks. It also allows jclouds developers to use >> significantly less code when developing complex domain classes that need to >> be reused in list/create/update API calls.</p> >> +]]></content> >> + </entry> >> + >> + <entry> >> >> <id>http://jclouds.apache.org/blog/2014/08/04/1-release-2-committers</id> >> <title type="html"><![CDATA[1 release, 2 committers...a busy week for >> jclouds!]]></title> >> <link >> href="http://jclouds.apache.org/blog/2014/08/04/1-release-2-committers"/> >> @@ -480,8 +605,7 @@ >> >> <p>For example, the following syntax can be used in karaf directly, or via >> the <a href="https://github.com/jclouds/jclouds-cli">jclouds cli</a> to >> start a node in any supported cloud and bootstrap chef recipes.</p> >> >> -<div class="highlight"><pre><code class="bash">karaf@root>node-create >> --adminAccess --recipe chef/java::openjdk karaf >> -</code></pre></div> >> +<div class="highlight"><pre><code class="bash">karaf@root>node-create >> --adminAccess --recipe chef/java::openjdk karaf</code></pre></div> >> >> >> <h2>What else is in 1.5.4?</h2> >> @@ -492,16 +616,14 @@ >> >> <p><a href="https://github.com/everett-toews">Everett</a> modernized >> support for <strong>rackspace-cloudloadbalancers-us</strong> and >> <strong>uk</strong> is now available. This includes syntactic sugar such as >> auto-pagination and easy transforms.</p> >> >> -<div class="highlight"><pre><code class="java"><span >> class="n">FluentIterable</span><span class="o"><</span><span >> class="n">HostAndPort</span><span class="o">></span> <span >> class="n">sockets</span> <span class="o">=</span> <span >> class="n">clb</span><span class="o">.</span><span >> class="na">getLoadBalancerApiForZone</span><span class="o">(</span><span >> class="n">zone</span><span class="o">).</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">concat</span><span class="o">().</span><span >> class="na">transform</span><span class="o">(</span><span >> class="n">converter</span><span class="o">);</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="java"><span >> class="n">FluentIterable</span><span class="o"><</span><span >> class="n">HostAndPort</span><span class="o">></span> <span >> class="n">sockets</span> <span class="o">=</span> <span >> class="n">clb</span><span class="o">.</span><span >> class="na">getLoadBalancerApiForZone</span><span class="o">(</span><span >> class="n">zone</span><span class="o">).</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">concat</span><span class="o">().</span><span >> class="na">transform</span><span class="o">(</span><span >> class="n">converter</span><span class="o">);</span></code></pre></div> >> >> >> <h3>Nova Server Diagnostics</h3> >> >> <p>Some implementations of Nova have diagnostic information available. >> Thanks to <a href="https://github.com/LeanderBB">Leander</a>, you can now >> discover this capability at runtime.</p> >> >> -<div class="highlight"><pre><code class="java"><span >> class="n">Optional</span><span class="o"><</span><span >> class="n">Map</span><span class="o">></span> <span >> class="n">diagnosticInfo</span> <span class="o">=</span> <span >> class="n">novaApi</span><span class="o">.</span><span >> class="na">getServerApiForZone</span><span class="o">(</span><span >> class="s">"az-1.region-a.geo-1"</span><span >> class="o">).</span><span class="na">getDiagnostics</span><span >> class="o">(</span><span class="n">serverId</span><span class="o">);</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="java"><span >> class="n">Optional</span><span class="o"><</span><span >> class="n">Map</span><span class="o">></span> <span >> class="n">diagnosticInfo</span> <span class="o">=</span> <span >> class="n">novaApi</span><span class="o">.</span><span >> class="na">getServerApiForZone</span><span class="o">(</span><span >> class="s">"az-1.region-a.geo-1"</span><span >> class="o">).</span><span class="na">getDiagnostics</span><span >> class="o">(</span><span class="n">serverId</span><span >> class="o">);</span></code></pre></div> >> >> >> <h3>S3 Multi-Object delete</h3> >> @@ -509,8 +631,7 @@ >> <p><a href="http://maginatics.com/">Maginatics</a> have BlobStore >> containers with over a billion objects in them. S3 containers (buckets) can >> now be cleared with 1/1000 the requests, thanks to <a >> href="https://twitter.com/andreisavu">Andrei</a>'s additional support of S3 >> multi-delete.</p> >> >> <div class="highlight"><pre><code class="java"><span >> class="n">DeleteResult</span> <span class="n">result</span> <span >> class="o">=</span> <span class="n">s3Api</span><span class="o">.</span><span >> class="na">deleteObjects</span><span class="o">(</span><span >> class="n">container</span><span class="o">,</span> <span >> class="n">keys</span><span class="o">);</span> >> -<span class="n">assertEquals</span><span class="o">(</span><span >> class="n">result</span><span class="o">.</span><span >> class="na">size</span><span class="o">(),</span> <span >> class="n">keys</span><span class="o">.</span><span >> class="na">size</span><span class="o">());</span> >> -</code></pre></div> >> +<span class="n">assertEquals</span><span class="o">(</span><span >> class="n">result</span><span class="o">.</span><span >> class="na">size</span><span class="o">(),</span> <span >> class="n">keys</span><span class="o">.</span><span >> class="na">size</span><span class="o">());</span></code></pre></div> >> >> >> <h2>What's next</h2> >> @@ -602,8 +723,7 @@ >> >> <h3>Lazy advance through all your metrics:</h3> >> >> -<div class="highlight"><pre><code class="java"><span >> class="n">FluentIterable</span><span class="o"><</span><span >> class="n">Metric</span><span class="o">></span> <span >> class="n">allMetrics</span> <span class="o">=</span> <span >> class="n">cloudwatch</span><span class="o">.</span><span >> class="na">getMetricApi</span><span class="o">().</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">concat</span><span class="o">();</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="java"><span >> class="n">FluentIterable</span><span class="o"><</span><span >> class="n">Metric</span><span class="o">></span> <span >> class="n">allMetrics</span> <span class="o">=</span> <span >> class="n">cloudwatch</span><span class="o">.</span><span >> class="na">getMetricApi</span><span class="o">().</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">concat</span><span class="o">();</span></code></pre></div> >> >> >> <h3>Â Advance only until we find the load balancer we want:</h3> >> @@ -611,14 +731,12 @@ >> <div class="highlight"><pre><code class="java"><span >> class="n">Optional</span><span class="o"><</span><span >> class="n">LoadBalancer</span><span class="o">></span> <span >> class="n">firstInterestingLoadBalancer</span> <span class="o">=</span> <span >> class="n">elb</span> >> <span class="o">.</span><span class="na">getLoadBalancerApi</span><span >> class="o">().</span><span class="na">list</span><span class="o">()</span> >> <span class="o">.</span><span class="na">concat</span><span >> class="o">()</span> >> - <span class="o">.</span><span class="na">firstMatch</span><span >> class="o">(</span><span class="n">isInterestingLB</span><span >> class="o">());</span> >> -</code></pre></div> >> + <span class="o">.</span><span class="na">firstMatch</span><span >> class="o">(</span><span class="n">isInterestingLB</span><span >> class="o">());</span></code></pre></div> >> >> >> <h3>Get only the first page of database instances</h3> >> >> -<div class="highlight"><pre><code class="java"><span >> class="n">IterableWithMarker</span><span class="o"><</span><span >> class="n">Instance</span><span class="o">></span> <span >> class="n">firstPage</span> <span class="o">=</span> <span >> class="n">rds</span><span class="o">.</span><span >> class="na">getInstanceApi</span><span class="o">().</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">get</span><span class="o">(</span><span class="mi">0</span><span >> class="o">);</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="java"><span >> class="n">IterableWithMarker</span><span class="o"><</span><span >> class="n">Instance</span><span class="o">></span> <span >> class="n">firstPage</span> <span class="o">=</span> <span >> class="n">rds</span><span class="o">.</span><span >> class="na">getInstanceApi</span><span class="o">().</span><span >> class="na">list</span><span class="o">().</span><span >> class="na">get</span><span class="o">(</span><span class="mi">0</span><span >> class="o">);</span></code></pre></div> >> >> >> <p>The above syntax is being worked through relevant apis. In order to try >> it out, grab jclouds 1.5.0-beta.7 (releasing today), and use any of the >> following methods:</p> >> @@ -655,8 +773,7 @@ >> <span class="k">for</span> <span class="o">(</span><span >> class="n">Tenant</span> <span class="n">tenant</span> <span >> class="o">:</span> <span class="n">adminClient</span><span >> class="o">.</span><span class="na">listTenants</span><span >> class="o">())</span> <span class="o">{</span> >> <span class="c1">// ...</span> >> <span class="o">}</span> >> -<span class="o">}</span> >> -</code></pre></div> >> +<span class="o">}</span></code></pre></div> >> >> >> <p>Also pro, is our new Amazon CloudWatch support from Jeremy Whitlock. >> This is our first complete renovation of an AWS api to have the same >> look/feel as our new OpenStack stuff. Just add a dependency on >> <em>org.jclouds.providers/aws-cloudwatch</em> and you can do this!</p> >> @@ -671,8 +788,7 @@ >> <span class="k">for</span> <span class="o">(</span><span >> class="n">Metric</span> <span class="n">metric</span> <span >> class="o">:</span> <span class="n">metricClient</span><span >> class="o">.</span><span class="na">listMetrics</span><span >> class="o">())</span> <span class="o">{</span> >> <span class="c1">// ...</span> >> <span class="o">}</span> >> -<span class="o">}</span> >> -</code></pre></div> >> +<span class="o">}</span></code></pre></div> >> >> >> <p>And for the jenkins users, we also have an api for remote job and >> computer control, at <em>org.jclouds.labs/jenkins</em>!</p> >> @@ -681,8 +797,7 @@ >> <span class="n">RestContext</span> <span class="n">localhost</span> <span >> class="o">=</span> <span class="n">contextBuilder</span><span >> class="o">.</span><span class="na">build</span><span class="o">();</span> >> >> <span class="n">Node</span> <span class="n">master</span> <span >> class="o">=</span> <span class="n">localhost</span><span >> class="o">.</span><span class="na">getApi</span><span >> class="o">().</span><span class="na">getMaster</span><span >> class="o">();</span> >> -<span class="n">localhost</span><span class="o">.</span><span >> class="na">getJobClient</span><span class="o">().</span><span >> class="na">createFromXML</span><span class="o">(</span><span >> class="s">"newJob"</span><span class="o">,</span> <span >> class="n">xmlAsString</span><span class="o">);</span> >> -</code></pre></div> >> +<span class="n">localhost</span><span class="o">.</span><span >> class="na">getJobClient</span><span class="o">().</span><span >> class="na">createFromXML</span><span class="o">(</span><span >> class="s">"newJob"</span><span class="o">,</span> <span >> class="n">xmlAsString</span><span class="o">);</span></code></pre></div> >> >> >> <p>This is especially helpful with the new <a >> href="https://github.com/jenkinsci/jclouds-plugin">jclouds-plugin</a>, which >> uses jclouds to spin up new slaves and publish artifacts to BlobStore. Tons >> more in there, too.</p> >> @@ -710,14 +825,12 @@ >> <div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="nf">use</span> <span >> class="o">'</span><span class="ss">'org.jclouds.compute2</span><span >> class="p">)</span> >> <span class="p">(</span><span class="nb">import </span><span >> class="o">'</span><span >> class="ss">'org.jclouds.scriptbuilder.statements.login.AdminAccess</span><span >> class="p">)</span> >> <span class="p">(</span><span class="k">def </span><span >> class="nv">compute</span> <span class="p">(</span><span >> class="nf">compute-service</span> <span >> class="s">"hpcloud-compute"</span> <span >> class="s">"tenantId:ACCESSKEY"</span> <span >> class="s">"SECRETKEY"</span> <span class="ss">:slf4j</span> >> <span class="ss">:sshj</span><span class="p">))</span> >> -<span class="p">(</span><span class="nf">create-node</span> <span >> class="nv">compute</span> <span class="s">"test"</span> <span >> class="p">(</span><span class="nf">build-template</span> <span >> class="nv">compute</span> <span class="p">{</span> <span >> class="ss">:run-script</span> <span class="p">(</span><span >> class="nf">AdminAccess/standard</span><span class="p">)</span> <span >> class="p">}</span> <span class="p">))</span> >> -</code></pre></div> >> +<span class="p">(</span><span class="nf">create-node</span> <span >> class="nv">compute</span> <span class="s">"test"</span> <span >> class="p">(</span><span class="nf">build-template</span> <span >> class="nv">compute</span> <span class="p">{</span> <span >> class="ss">:run-script</span> <span class="p">(</span><span >> class="nf">AdminAccess/standard</span><span class="p">)</span> <span >> class="p">}</span> <span class="p">))</span></code></pre></div> >> >> >> <p>Here's an example of how to do the same on <a >> href="https://trystack.org/">TryStack</a>, authenticating w/ user & pass >> as opposed to key, via our <a >> href="https://github.com/jclouds/jclouds-examples/tree/master/compute-basics">java >> example</a>:</p> >> >> -<div class="highlight"><pre><code class="bash">java -jar >> target/compute-basics-jar-with-dependencies.jar trystack-nova tenantId:user >> password mygroup add >> -</code></pre></div> >> +<div class="highlight"><pre><code class="bash">java -jar >> target/compute-basics-jar-with-dependencies.jar trystack-nova tenantId:user >> password mygroup add</code></pre></div> >> >> >> <p>In the group org.jclouds.labs, you'll find two more new and notable >> members of the jclouds family:</p> >> @@ -730,8 +843,7 @@ >> >> <p>You can try out virtualbox like any other api. For example, you can use >> the clojure above, only changing how you create the connection slightly:</p> >> >> -<div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="k">def </span><span class="nv">compute</span> >> <span class="p">(</span><span class="nf">compute-service</span> <span >> class="s">"virtualbox"</span> <span >> class="s">"administrator"</span> <span >> class="s">"12345"</span> <span class="ss">:sshj</span> <span >> class="ss">:slf4j</span><span class="p">))</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="k">def </span><span class="nv">compute</span> >> <span class="p">(</span><span class="nf">compute-service</span> <span >> class="s">"virtualbox"</span> <span >> class="s">"administrator"</span> <span >> class="s">"12345"</span> <span class="ss">:sshj</span> <span >> class="ss">:slf4j</span><span class="p">))</span></code></pre></div> >> >> >> <p>The code in labs will certainly change before we release a beta, but >> feel free to check them out. Meanwhile, you can try them out and give us >> feedback on #jclouds irc freenode or jclouds-dev google group!</p> >> @@ -740,8 +852,7 @@ >> >> <p>Oh, and don't forget to clean up your nodes :)</p> >> >> -<div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="nf">destroy-nodes-matching</span> <span >> class="nv">compute</span> <span class="p">(</span><span >> class="nb">constantly </span><span class="nv">true</span><span >> class="p">))</span> >> -</code></pre></div> >> +<div class="highlight"><pre><code class="clojure"><span >> class="p">(</span><span class="nf">destroy-nodes-matching</span> <span >> class="nv">compute</span> <span class="p">(</span><span >> class="nb">constantly </span><span class="nv">true</span><span >> class="p">))</span></code></pre></div> >> >> >> >> @@ -862,8 +973,7 @@ >> >> <div class="highlight"><pre><code class="java"><span >> class="n">future</span> <span class="o">=</span> <span >> class="n">client</span><span class="o">.</span><span >> class="na">submitScriptOnNode</span><span class="o">(</span><span >> class="n">node</span><span class="o">.</span><span >> class="na">getId</span><span class="o">(),</span> >> <span class="n">AdminAccess</span><span >> class="o">.</span><span class="na">builder</span><span >> class="o">().</span><span class="na">adminUsername</span><span >> class="o">(</span><span class="s">"foo"</span><span >> class="o">).</span><span class="na">build</span><span class="o">(),</span> >> - <span class="n">nameTask</span><span >> class="o">(</span><span class="s">"adminUpdate"</span><span >> class="o">));</span> >> -</code></pre></div> >> + <span class="n">nameTask</span><span >> class="o">(</span><span class="s">"adminUpdate"</span><span >> class="o">));</span></code></pre></div> >> >> >> <p>As always, we keep our <a >> href="https://github.com/jclouds/jclouds-examples">examples site</a> up to >> date so you can see how to work this stuff. Next release will be in >> approximately 1-months time. Look out for progress including <a >> href="http://www.vmware.com/products/vcloud-director/overview.html">vCloud >> 1.5</a>, <a href="http://voxel.net/voxcloud">Voxel</a>, and <a >> href="https://www.virtualbox.org/">VirtualBox</a>.</p> >> @@ -876,41 +986,4 @@ >> ]]></content> >> </entry> >> >> - <entry> >> - >> <id>http://jclouds.apache.org/blog/2009/05/13/catching-exceptions-with-less-keystrokes</id> >> - <title type="html"><![CDATA[Catching exceptions with fewer >> keystrokes]]></title> >> - <link >> href="http://jclouds.apache.org/blog/2009/05/13/catching-exceptions-with-less-keystrokes"/> >> - <updated>2009-05-13T00:00:00Z</updated> >> - <content type="html"><![CDATA[<p>Some of us hate checked exceptions, >> but still use them for one reason or another. A common problem we have is >> unnecessary exception nesting, or runtime swallowing. This often leads to >> the all to familiar and crufty code with a million catch blocks. jclouds has >> a slightly different approach that strikes a balance, allowing checked >> exceptions to be dealt with, but without the pain of so many lines of >> repetitious code.</p> >> - >> -<div class="highlight"><pre><code class="java"><span class="k">try</span> >> <span class="o">{</span> >> -<span class="o">}</span> <span class="k">catch</span> <span >> class="o">(</span><span class="n">Exception</span> <span >> class="n">e</span><span class="o">)</span> <span class="o">{</span> >> - <span class="n">Utils</span><span class="o">.<</span><span >> class="n">ApplicationException</span><span class="o">></span><span >> class="n">rethrowIfRuntimeOrSameType</span><span class="o">(</span><span >> class="n">e</span><span class="o">);</span> >> - <span class="k">throw</span> <span class="k">new</span> <span >> class="nf">ApplicationException</span><span class="o">(</span><span >> class="s">"Error applying stuff"</span><span class="o">,</span> >> <span class="n">e</span><span class="o">);</span> >> -<span class="o">}</span> >> -</code></pre></div> >> - >> - >> -<p>This code does what it says, preventing us from unnecessarily nesting >> application exceptions or swallowing runtimes.</p> >> - >> -<p>Now, this code shouldn't work, as current versions of java hava a >> generic type erasure problem. The reason it does work is a somewhat hackish >> line in the rethrowIfRuntimeOrSameType method:</p> >> - >> -<div class="highlight"><pre><code class="java"><span class="k">if</span> >> <span class="o">(</span><span class="n">e</span> <span >> class="k">instanceof</span> <span class="n">RuntimeException</span><span >> class="o">)</span> <span class="o">{</span> >> - <span class="k">throw</span> <span class="o">(</span><span >> class="n">RuntimeException</span><span class="o">)</span> <span >> class="n">e</span><span class="o">;</span> >> -<span class="o">}</span> <span class="k">else</span> <span >> class="o">{</span> >> - <span class="k">try</span> <span class="o">{</span> >> - <span class="k">throw</span> <span class="o">(</span><span >> class="n">E</span><span class="o">)</span> <span class="n">e</span><span >> class="o">;</span> >> - <span class="o">}</span> <span class="k">catch</span> <span >> class="o">(</span><span class="n">ClassCastException</span> <span >> class="n">throwAway</span><span class="o">)</span> <span class="o">{</span> >> - <span class="c1">// using cce as there's no way to do >> instanceof E in current java</span> >> - <span class="o">}</span> >> -<span class="o">}</span> >> -</code></pre></div> >> - >> - >> -<p>The trick is that we try to force the exception we caught into the >> generic type. If that fails, we know it wasn't that type and that we should >> wrap, log, etc.</p> >> - >> -<p>If nothing else, I hope you enjoy the perspective!</p> >> -]]></content> >> - </entry> >> - >> </feed> >> >> Modified: jclouds/site-content/blog/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/index.html?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- jclouds/site-content/blog/index.html (original) >> +++ jclouds/site-content/blog/index.html Thu Sep 4 15:18:35 2014 >> @@ -150,6 +150,12 @@ >> <p><a >> href="https://wiki.apache.org/jclouds/How%20to%20Contribute%20Documentation">Write >> a guest post!</a></p> >> >> >> +<h3><a class="text-primary" href="/blog/2014/09/03/better-builders">Better >> Builders with jclouds!</a></h3> >> +<span class="text-muted">03 September 2014, by Zack Shoylev</span> >> +<p>If you are a new jclouds developer, or even if you are already >> developing jclouds support for any of the OpenStack or Rackspace APIs, you >> have likely seen the domain classes that are used throughout the the jclouds >> codebase. >> +These classes are used to represent OpenStack resources, particularly the >> JSON structures supported by OpenStack APIs. >> +</p> >> + >> <h3><a class="text-primary" >> href="/blog/2014/08/04/1-release-2-committers">1 release, 2 committers...a >> busy week for jclouds!</a></h3> >> <span class="text-muted">04 August 2014, by <a >> href="http://blog.xebialabs.com/author/aphillips/">Andrew Phillips</a></span> >> <p>There's a lot going on this week for the jclouds community. Most >> importantly, we're really pleased to introduce two new committers: Andrea >> Turli and Chris Custine. >> @@ -170,11 +176,6 @@ >> <p>The Google Summer of Code (GSoC) accepted projects have been announced >> and we will have 3 students working on jclouds related projects! >> </p> >> >> -<h3><a class="text-primary" href="/blog/2014/03/04/jclouds-meetup">jclouds >> Meetup</a></h3> >> -<span class="text-muted">04 March 2014, by <a >> href="https://twitter.com/everett_toews">Everett Toews</a></span> >> -<p>Last night we held a jclouds meetup at Cloudera offices in San >> Francisco. It was a well attended meetup and there were a number of new >> faces along with our more regular group of attendees. We recorded the whole >> thing with Google Hangouts on Air and you can get to know everyone in the >> first 5 minutes! >> -</p> >> - >> >> >> <ul class="pagination text-center"> >> @@ -189,25 +190,25 @@ >> >> <li> >> >> - <a class="text-primary" href="/blog/page2">2</a> >> + <a class="text-primary" href="blog/page2">2</a> >> >> </li> >> >> <li> >> >> - <a class="text-primary" href="/blog/page3">3</a> >> + <a class="text-primary" href="blog/page3">3</a> >> >> </li> >> >> <li> >> >> - <a class="text-primary" href="/blog/page4">4</a> >> + <a class="text-primary" href="blog/page4">4</a> >> >> </li> >> >> <li> >> >> - <a class="text-primary" href="/blog/page5">5</a> >> + <a class="text-primary" href="blog/page5">5</a> >> >> </li> >> >> >> Modified: jclouds/site-content/blog/page2/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/page2/index.html?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- jclouds/site-content/blog/page2/index.html (original) >> +++ jclouds/site-content/blog/page2/index.html Thu Sep 4 15:18:35 2014 >> @@ -150,6 +150,11 @@ >> <p><a >> href="https://wiki.apache.org/jclouds/How%20to%20Contribute%20Documentation">Write >> a guest post!</a></p> >> >> >> +<h3><a class="text-primary" href="/blog/2014/03/04/jclouds-meetup">jclouds >> Meetup</a></h3> >> +<span class="text-muted">04 March 2014, by <a >> href="https://twitter.com/everett_toews">Everett Toews</a></span> >> +<p>Last night we held a jclouds meetup at Cloudera offices in San >> Francisco. It was a well attended meetup and there were a number of new >> faces along with our more regular group of attendees. We recorded the whole >> thing with Google Hangouts on Air and you can get to know everyone in the >> first 5 minutes! >> +</p> >> + >> <h3><a class="text-primary" >> href="/blog/2014/03/03/joining-the-asf-new-site-and-jclouds-1-7">Joining the >> ASF, new site, and jclouds 1.7!</a></h3> >> <span class="text-muted">03 March 2014, by Ignasi Barrera</span> >> <p>It's been a while since our last blog post, and lots has happened since >> then. There have been many things that have kept us busy, and finally, all >> the hard work is starting to show up. During this time, we've: >> @@ -170,11 +175,6 @@ >> <p>jclouds community is an international group with over 100 contributors >> since we started in early 2009. The idea of holidays vary, but we decided >> Mistletoe as an appropriate codename for jclouds 1.5.4. Here's why. >> </p> >> >> -<h3><a class="text-primary" >> href="/blog/2012/11/17/jclouds-1-5-3-out-the-door">jclouds 1.5.3 out the >> door</a></h3> >> -<span class="text-muted">17 November 2012, by Adrian Cole</span> >> -<p>Released on 2012-11-14, jclouds 1.5.3 includes minor fixes, and a few >> important updates. >> -</p> >> - >> >> >> <ul class="pagination text-center"> >> @@ -191,25 +191,25 @@ >> >> <li> >> >> - <a class="text-primary" href="/blog/page2">2</a> >> + <a class="text-primary" href="blog/page2">2</a> >> >> </li> >> >> <li> >> >> - <a class="text-primary" href="/blog/page3">3</a> >> + <a class="text-primary" href="blog/page3">3</a> >> >> </li> >> >> <li> >> >> - <a class="text-primary" href="/blog/page4">4</a> >> + <a class="text-primary" href="blog/page4">4</a> >> >> </li> >> >> <li> >> >> - <a class="text-primary" href="/blog/page5">5</a> >> + <a class="text-primary" href="blog/page5">5</a> >> >> </li> >> >> >> Modified: jclouds/site-content/blog/page3/index.html >> URL: >> http://svn.apache.org/viewvc/jclouds/site-content/blog/page3/index.html?rev=1622496&r1=1622495&r2=1622496&view=diff >> ============================================================================== >> --- jclouds/site-content/blog/page3/index.html (original) >> +++ jclouds/site-content/blog/page3/index.html Thu Sep 4 15:18:35 2014 >> @@ -150,6 +150,11 @@ >> <p><a >> href="https://wiki.apache.org/jclouds/How%20to%20Contribute%20Documentation">Write >> a guest post!</a></p> >> >> >> +<h3><a class="text-primary" >> href="/blog/2012/11/17/jclouds-1-5-3-out-the-door">jclouds 1.5.3 out the >> door</a></h3> >> +<span class="text-muted">17 November 2012, by Adrian Cole</span> >> +<p>Released on 2012-11-14, jclouds 1.5.3 includes minor fixes, and a few >> important updates. >> +</p> >> + >> <h3><a class="text-primary" >> href="/blog/2012/11/09/500-jclouds-builds-on-buildhive-and-counting">500 >> jclouds builds on BuildHive and counting...</a></h3> >> <span class="text-muted">09 November 2012, by Adrian Cole</span> >> <p>At jclouds, we've been running our Jenkins continuous integration jobs >> in CloudBees' DEV@cloud for a while now (CloudBees has a FOSS programme). We >> also have an active and ever-increasing contributor community, which amongst >> others means... lots of pull requests. >> @@ -170,11 +175,6 @@ >> <p>We are very near beta, I promise! In the mean time, we just cut a new >> codebase with a bunch of cool new toys. Here's a few. Thanks to Adam Lowe, >> we are getting even deeper into OpenStack with more Keystone support than >> ever. Setup your code to pull org.jclouds.labs/openstack-keystone, and you >> can do stuff like this. >> </p> >> >> -<h3><a class="text-primary" >> href="/blog/2012/03/23/take-a-peek-at-vcloud-director-1-5-openstack-and">Take >> a peek at vCloud Director 1.5, OpenStack, and VirtualBox</a></h3> >> -<span class="text-muted">23 March 2012, by Adrian Cole</span> >> -<p>The jclouds team have been working very hard lately, particularly on a >> few new apis. We've decided to cage them no longer and cut jclouds >> 1.5.0-alpha.1. Most notably, we've added the openstack-nova api, and three >> new providers, all of which discovered via OpenStack Keystone v2.0. >> -</p> >> - >> >> >> <ul class="pagination text-center"> >> @@ -191,25 +191,25 @@ >> >> <li> >> >> - <a class="text-primary" href="/blog/page2">2</a> >> + <a class="text-primary" href="blog/page2">2</a> >> >> </li> >> >> <li> >> >> - <a class="text-primary" href="/blog/page3">3</a> >> + <a class="text-primary" href="blog/page3">3</a> >> >> </li> >> >> <li> >> >> - <a class="text-primary" href="/blog/page4">4</a> >> + <a class="text-primary" href="blog/page4">4</a> >> >> </li> >> >> <li> >> >> - <a class="text-primary" href="/blog/page5">5</a> >> + <a class="text-primary" href="blog/page5">5</a> >> >> </li> >> >> >>