<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" version="2.0">
  <channel>
    <title>Project Automation Experience</title>
    <link>http://projectautomationexperience.com</link>
    <description>Project Automation Experience</description>
    <item>
      <title>CodeSherpas is looking for new talent</title>
      <link>http://projectautomationexperience.com/blog/david_bock/2012/06/codesherpas_is_looking_for_new_talent</link>
      <description>&lt;p&gt;Just over 5 years ago we started CodeSherpas with a vision - &lt;strong&gt;the nature of software development is changing, and we wanted to be on the forefront of that change.&lt;/strong&gt; Our jobs are many and varied - sometimes training and mentoring, sometimes augmenting existing staff, sometimes the project is ours and ours alone. Sometimes we work at home, sometimes on client-site.  We bring the deep experience we have developed to bear on our client&amp;#39;s projects, and have a strong reputation doing so.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The time has come for us to broaden ourselves; we are looking for a couple of passionate, self-motivated software engineers who want the opportunity to take their expertise to the next level.&lt;/strong&gt; Are you interested in working for a company where &lt;strong&gt;your skillset is the product, and the company invests in it?&lt;/strong&gt; Are you interested in working someplace where even the owners write code, and there are no &amp;#39;pointy-haired bosses&amp;#39;?  Are you interested in solving a variety of interesting technical problems?  Have you been dabbling in recently emerged technologies and want the opportunity to use them full-time in mission-critical production applications?&lt;/p&gt;
&lt;p&gt;We currently spend most of our time in a web-centric development stack.  To us that means:  &lt;strong&gt;Ruby, Java, Javascript, CSS, HTML5, JQuery, NodeJS, Backbone, MySQL, Redis, Linux, OSX, and so on.&lt;/strong&gt; We also occasionally dabble in &lt;strong&gt;Objective C and Clojure&lt;/strong&gt;, and see those technologies as crucial to the future.  When we run a project we prefer 2 week iterations, constant feature delivery, and reflection on the work to improve ourselves.  We know and love git.  We like to publish, speak at conferences, record screencasts, and promote the local user group communities. If you think you can contribute to a team doing these things, we want to talk to you.&lt;/p&gt;
&lt;p&gt;As consultants, our jobs tend to take us around the &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Northern_Virginia" rel="wikipedia" target="_blank" title="Northern Virginia"&gt;Northern Virginia&lt;/a&gt; and Washington DC area.  Sometimes we work at home, sometimes in the Reston area, and sometimes in DC.  We know commuting in the &lt;a class="zem_slink" href="http://maps.google.com/maps?ll=38.8867583333,-77.041625&amp;amp;spn=0.01,0.01&amp;amp;q=38.8867583333,-77.041625 (Washington%20Metropolitan%20Area)&amp;amp;t=h" rel="geolocation" target="_blank" title="Washington Metropolitan Area"&gt;DC metro area&lt;/a&gt; is tough, we do it ourselves. Despite this, we strive to maintain a healthy work-life balance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We&amp;#39;re not looking for rock stars... we&amp;#39;re looking for orchestra members.  We&amp;#39;re not looking for ninjas... we&amp;#39;re looking for Sherpas.  We do the technical heavy-lifting.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Does that sound interesting?  Lets talk.&lt;/p&gt;</description>
      <pubDate>Tue, 19 Jun 2012 07:44:00 CDT</pubDate>
      <guid isPermaLink="true">http://blog.codesherpas.com/on_the_path/2012/06/codesherpas-is-looking-for-new-talent.html</guid>
      <dc:creator>David Bock</dc:creator>
    </item>
    <item>
      <title>Goetz's First Law</title>
      <link>http://projectautomationexperience.com/blog/david_bock/2012/06/goetz_s_first_law</link>
      <description>&lt;blockquote&gt;"Its never any one feature that causes problems; it is the interaction of otherwise reasonable-seeming features."&lt;/blockquote&gt;

&lt;p&gt;In a recent conversation with a number of &lt;a href="http://www.nofluffjuststuff.com/conference/speaker/list"&gt;NFJS speakers&lt;/a&gt;, David Sletten (via his brother Brian) brought up a tricky &lt;a href="http://www.javapuzzlers.com/"&gt;Java puzzler&lt;/a&gt; - a piece of code that is seemingly simple, but doesn't do quite what you'd expect.  Consider:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
Arrays.asList(new Integer[] {1, 2, 3}).size();
Arrays.asList(1, 2, 3).size();
Arrays.asList(new int[] {1, 2, 3}).size();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To make a long story short, any reasonable first-reading of this code would expect all three examples to return '3', yet the bottom one returns '1'.  Why?&lt;/p&gt;

&lt;p&gt;Brian Goetz, who has the esteemed title of "Architect for the Java Language and Libraries" gave a clue that leads to the answer when he said "Hint: asList is a generic method. What type is being inferred for T?"&lt;/p&gt;

&lt;p&gt;This led to a conversation that only the nerdiest of nerds lubricated with the finest of scotches would dare sit through. Brian eventually concludes with the statement, "The bipartite nature of the type system is the root cause here; int is not an Object, but int[] is.  Mix that with varargs' attempt to conflate T... with T[], and...bam, astonishment.  Its never any one feature that causes problems; it is the interaction of otherwise reasonable-seeming features."&lt;/p&gt;

&lt;p&gt;That last sentence was quickly seized upon as a profound truth in software development and dubbed "Goetz's first law".  &lt;/p&gt;

&lt;p&gt;The code example above isn't nearly as important as the sentiment that inspired the law.  Since he said that, I've seen virtually every problem I'm encountering as a variation of this.&lt;/p&gt;</description>
      <pubDate>Mon, 18 Jun 2012 14:44:00 CDT</pubDate>
      <guid isPermaLink="true">http://blog.codesherpas.com/on_the_path/2012/06/goetzs-first-law.html</guid>
      <dc:creator>David Bock</dc:creator>
    </item>
    <item>
      <title>A Recurring Billing System with Stripe</title>
      <link>http://projectautomationexperience.com/blog/brian_sam-bodden/2012/06/a_recurring_billing_system_with_stripe</link>
      <description>&lt;p style="font-style: italic;"&gt;These notes are meant to answer some basic questions about using Stripe for billing, and also to answer some questions about implementation which are not covered in the Stripe documentation and forums. This is not a comprehensive overview by any means. If you find errors, please let me know and I will fix them. The examples will use the &lt;a href="https://github.com/stripe/stripe-ruby"&gt;stripe-ruby&lt;/a&gt; gem (v1.7.0). A list of basic operations can be found in Stripe's &lt;a href="https://stripe.com/docs/api?lang=ruby"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Stripe recommends downloading the gem over SSL from the mirror at &lt;a href="https://code.stripe.com"&gt;https://code.stripe.com&lt;/a&gt;.&lt;/p&gt;

&lt;pre class="brush: shell;"&gt;sudo gem install --source https://code.stripe.com stripe
&lt;/pre&gt;

&lt;p&gt;Here is a list of resources which I have found useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://railscasts.com/episodes/288-billing-with-stripe"&gt;Railscasts episode 288&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/1750368"&gt;Stripe sample checkout form&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://answers.stripe.com/"&gt;https://answers.stripe.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stripe.com/docs/testing"&gt;https://stripe.com/docs/testing&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
&lt;a name="creating-subscription-plans" class="anchor" href="#creating-subscription-plans"&gt;&lt;span class="mini-icon mini-icon-link"&gt;&lt;/span&gt;
&lt;/a&gt;Creating Subscription Plans&lt;/h2&gt;

&lt;p&gt;Plans can be created through the Stripe Dashboard or the API. Since plans will not change often, it’s easy to create them through the Dashboard and retrieve them from the application via the API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://a248.e.akamai.net/camo.github.com/d8749f856106dea6e4fbc4c0dffe7339f2ea4010/687474703a2f2f692e696d6775722e636f6d2f324d6b4a622e706e673f32" target="_blank"&gt;&lt;img src="https://a248.e.akamai.net/camo.github.com/d8749f856106dea6e4fbc4c0dffe7339f2ea4010/687474703a2f2f692e696d6775722e636f6d2f324d6b4a622e706e673f32" alt="Stripe Dashboard - New Plan" style="max-width:100%;" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;Stripe::Plan.create(
  :amount =&amp;gt; 999,
  :interval =&amp;gt; 'month',
  :name =&amp;gt; 'My Basic Plan',
  :currency =&amp;gt; 'usd',
  :id =&amp;gt; 'basic'
)
&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Create Token with Stripe.js&lt;/h2&gt;

&lt;p&gt;Stripe provides a javascript library which sends encrypted credit card and cardholder data to Stripe’s servers from the browser. Card info is sent (along with the accounts public key) directly to Stripe and is never handled by host application.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;// https://gist.github.com/1750368
Stripe.setPublishableKey('pk_YOUR_PUBLISHABLE_KEY');

Stripe.createToken({
  number: $('.card-number').val(),
  cvc: $('.card-cvc').val(),
  exp_month: $('.card-expiry-month').val(),
  exp_year: $('.card-expiry-year').val()
}, stripeResponseHandler);
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The response includes the ID of the created &lt;a href="https://stripe.com/docs/api?lang=ruby#token_object"&gt;card token&lt;/a&gt; if successful, and relevant error messages otherwise. The token represents a valid credit card stored by Stripe’s servers. Card tokens do not represent charges of any kind.&lt;/p&gt;

&lt;h2&gt;Token Object&lt;/h2&gt;

&lt;p&gt;A  The host server can retrieve information about the card by &lt;a href="https://stripe.com/docs/api?lang=ruby#retrieve_token"&gt;retrieving the token&lt;/a&gt; referenced by the token ID. The response will contain basic card details including the last four digits of the card, instead of the entire number.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;Stripe::Token.retrieve("tok_00000000000000")
&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Create Customer&lt;/h2&gt;

&lt;p&gt;The card token ID can then be submitted to the host server. Card tokens can be used to create a &lt;a href="https://stripe.com/docs/api?lang=ruby#create_charge"&gt;one-time charge&lt;/a&gt; or to create a &lt;a href="https://stripe.com/docs/api?lang=ruby#customer_object"&gt;customer&lt;/a&gt; with a subscription. The relationship between a customer and a plan is described by a &lt;a href="https://stripe.com/docs/api?lang=ruby#subscription_object"&gt;subscription&lt;/a&gt;. Subscriptions can be updated or canceled through the customer object.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;Stripe::Customer.create(
  :description =&amp;gt; "Customer for jim@example.com",
  :plan =&amp;gt; "basic",
  :card =&amp;gt; "tok_00000000000000" # obtained with Stripe.js
)
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Many applications will offer a free plan. Stripe will allow plans to have an amount of 0 (zero). Customers can be subscribed to a free plan without providing credit card information. Subscribing free users to a free plan could make the upgrade process simpler, since a customer record will already exist. Providing a card token is optional when creating a customer with a subscription to a free account.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;Stripe::Customer.create(
  :description =&amp;gt; "Customer for jim@example.com",
  :plan =&amp;gt; "my_free_plan_id"
)
&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Updating Customer Subscription&lt;/h2&gt;

&lt;p&gt;It’s likely that a host application will allow users to change to a different plan. In this case, the relevant customer object can be &lt;a href="https://stripe.com/docs/api#update_subscription"&gt;retrieved and updated&lt;/a&gt;. Updates can optionally be prorated.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;c = Stripe::Customer.retrieve("cus_00000000000000")
c.update_subscription(:plan =&amp;gt; "enterprise", :prorate =&amp;gt; true)
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Customers can only be updated from a free plan to a paid plan if a valid card token is provided with the request.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;c = Stripe::Customer.retrieve("cus_00000000000000")
c.update_subscription(:plan =&amp;gt; "pro", :card =&amp;gt; "tok_00000000000000" ,:prorate =&amp;gt; true)
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Customers can be updated from a paid plan to a free plan without providing a card token. In this case Stripe will still have the user’s active card on file; so if the user switches back to a paid plan, it is optional to include a card token with the update request.&lt;/p&gt;

&lt;p&gt;At this time, Stripe does not offer a way to remove an active card from a customer which is subscribed to a free plan.&lt;/p&gt;

&lt;h2&gt;Cancel Customer Subscription&lt;/h2&gt;

&lt;p&gt;When a user deletes their account or their customer record is no longer needed, the customer object can be &lt;a href="https://stripe.com/docs/api#delete_customer"&gt;retrieved and deleted&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;c = Stripe::Customer.retrieve("cus_00000000000000")
c.delete
&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Webhook Authentication&lt;/h2&gt;

&lt;p&gt;It is critical to properly authenticate webhooks. There are two &lt;a href="https://answers.stripe.com/questions/what-is-the-recommended-way-to-authenticate-a-webhook-callback"&gt;methods of authentication&lt;/a&gt; recommended by Stripe. The first (and simplest) method is to retrieve the event using the &lt;code&gt;id&lt;/code&gt; parameter of the webhook request.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;# in a Rails controller
def my_webhook_action
  # this will raise InvalidRequestError (status 404) if the event does not exist
  event = Stripe::Event.retrieve(params[:id])
  # safe to use the returned event object
  # ...
rescue Stripe::InvalidRequestError =&amp;gt; e
  logger.error "Unable to authenticate webhook request: #{e.message}"
  # 401 Unauthorized response
end
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The second method for authenticating webhooks is to use HTTP basic authentication. When setting the webhook url in the Stripe Dashboard, provide a username and password. See Railscasts &lt;a href="http://railscasts.com/episodes/82-http-basic-authentication"&gt;episode 82&lt;/a&gt; for details on implementing HTTP basic authentication in a Rails app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://a248.e.akamai.net/camo.github.com/cdd33f32c15d49bb3502738be2422aff599755c5/687474703a2f2f692e696d6775722e636f6d2f52713039382e706e67" target="_blank"&gt;&lt;img src="https://a248.e.akamai.net/camo.github.com/cdd33f32c15d49bb3502738be2422aff599755c5/687474703a2f2f692e696d6775722e636f6d2f52713039382e706e67" alt="Webhook url" style="max-width:100%;" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;Testing&lt;/h2&gt;

&lt;p&gt;If you are implementing your system in Ruby, I highly recommend the &lt;a href="9"&gt;VCR&lt;/a&gt; gem. For a good overview of VCR and it capabilities, watch Railscasts &lt;a href="http://railscasts.com/episodes/291-testing-with-vcr"&gt;episode 291&lt;/a&gt; *.&lt;/p&gt;

&lt;p&gt;It is important not to commit your secret api key to the repo. Use the &lt;a href="https://www.relishapp.com/myronmarston/vcr/v/2-1-1/docs/configuration/filter-sensitive-data"&gt;filter_sensitive_data&lt;/a&gt; configuration option to redact your private key from the recordings.&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;VCR.configure do |c|
  # ...
  c.filter_sensitive_data('[secret_key]') { Stripe.api_key }
end
&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Appendix&lt;/h2&gt;

&lt;p&gt;* Please note that some of the configuration syntax has changed in newer versions of the VCR gem:&lt;/p&gt;

&lt;div class="highlight"&gt;
&lt;pre class="brush: ruby;"&gt;# VCR.config do |c| # outdated
VCR.configure do |c| # new
  # ...
  # c.stub_with :fakeweb # outdated
  c.hook_into :fakeweb # new
end
&lt;/pre&gt;
&lt;/div&gt;


&lt;hr /&gt;</description>
      <pubDate>Mon, 11 Jun 2012 11:31:00 CDT</pubDate>
      <dc:creator>Brian Sam-Bodden</dc:creator>
    </item>
    <item>
      <title>Go beyond Java with CI server and Artifactory</title>
      <link>http://projectautomationexperience.com/blog/baruch_sadogursky/2012/05/go_beyond_java_with_ci_server_and_artifactory</link>
      <description>&lt;p&gt;During the last couple of years, continuous integration (CI) and automated release management methodologies have become much stronger in non-Java builds.&lt;/p&gt;
&lt;p&gt;Number of familiar tools are used for these methodologies, like the version control system to manages your sources, your build tool to actually build your software from sources and  your build server, which builds your software continuously using the build tool. But is there something else missing? Let&amp;#8217;s look at a simple diagram, which describes your CI process:&lt;/p&gt;
&lt;div class="c1"&gt;
&lt;div class="separator" style="clear:both;text-align:center;"&gt;&lt;a style="margin-left:1em;margin-right:1em;" href="http://jbaruch.files.wordpress.com/2012/05/image03.png"&gt;&lt;img src="http://jbaruch.files.wordpress.com/2012/05/image03.png?w=320&amp;h=203" alt="" width="320" height="203" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Developers fetch needed dependencies (3rd party libraries, other modules).&lt;/li&gt;
&lt;li&gt;Developers write new code.&lt;/li&gt;
&lt;li&gt;Code is committed to VCS.&lt;/li&gt;
&lt;li&gt;Build server polls VCS for changes.&lt;/li&gt;
&lt;li&gt;Once discovered, the build server builds the software: compiles it, runs tests, and assembles artifacts.&lt;/li&gt;
&lt;li&gt;Built artifacts are published to QA, staging, or even directly to the end users.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you can see, everything except stages 1 and 6 is well known and familiar. But what about those two stages? You need a dependency management mechanism for them.&lt;/p&gt;
&lt;p&gt;In this post, we’ll illustrate the options for automated builds with dependency management in non-Java builds or when not using .NET with NuGet (use it, if you can! &lt;a href="http://blogs.jfrog.org/2012/02/dependency-management-with-net-doing-it.html"&gt;Here&lt;/a&gt;’s our take about it). The proposed solution works for any kind of build, be it C, C++, C#, iOS and Objective C, Python, or whatever.&lt;/p&gt;
&lt;p&gt;So, let’s see how you can implement CI with dependency management for non-Java projects. Here are the options with their pros and cons:&lt;/p&gt;
&lt;/div&gt;
&lt;table border="1" cellspacing="0" cellpadding="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th width="2%"&gt;#&lt;/th&gt;
&lt;th width="20%"&gt;Solution&lt;/th&gt;
&lt;th width="39%"&gt;Pros&lt;/th&gt;
&lt;th width="39%"&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Dependencies in VCS&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Use proven build tools&lt;/li&gt;
&lt;li&gt;Simple setup – you use VCS anyhow&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;VCS won’t fit for binary dependencies. You can read why &lt;a href="http://blogs.jfrog.org/2012/02/dependency-management-with-net-doing-it.html"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Build tools with built-in dependency management like &lt;a href="http://maven.apache.org/"&gt;Maven&lt;/a&gt; and &lt;a href="http://gradle.org/"&gt;Gradle&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Build tool with dependency management&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;New tool to learn. Both Maven 2 and Gradle have a pretty steep learning curve.&lt;/li&gt;
&lt;li&gt;“Adapted” from Java. While&lt;span class="c0"&gt;&lt;a class="c4" href="http://mojo.codehaus.org/maven-native/native-maven-plugin/"&gt; &lt;/a&gt;&lt;/span&gt;&lt;span class="c3 c0"&gt;&lt;a class="c4" href="http://mojo.codehaus.org/maven-native/native-maven-plugin/"&gt;there&lt;/a&gt;&lt;/span&gt;&lt;span class="c0"&gt;&lt;a class="c4" href="http://java.freehep.org/freehep-nar-plugin/intro.html"&gt; &lt;/a&gt;&lt;/span&gt;&lt;span class="c3 c0"&gt;&lt;a class="c4" href="http://java.freehep.org/freehep-nar-plugin/intro.html"&gt;are&lt;/a&gt;&lt;/span&gt;&lt;span class="c0"&gt;&lt;a class="c4" href="http://gradle.org/docs/current/userguide/cpp.html"&gt; &lt;/a&gt;&lt;/span&gt;&lt;span class="c3 c0"&gt;&lt;a class="c4" href="http://gradle.org/docs/current/userguide/cpp.html"&gt;ways&lt;/a&gt;&lt;/span&gt;&lt;span class="c0"&gt; to build “native” applications with them (easier with Gradle, harder with Maven) it still feels, let’s say, artificial, imposing their new conventions.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="c16"&gt;
&lt;div class="c2 c17"&gt;3&lt;/div&gt;
&lt;/td&gt;
&lt;td class="c11"&gt;
&lt;div class="c1"&gt;&lt;span class="c0"&gt;Declare dependencies on builds in your build server&lt;/span&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td class="c21"&gt;
&lt;div class="c1 c5"&gt;
&lt;ul&gt;
&lt;li&gt;Use proven build tools&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="c1"&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td class="c18"&gt;
&lt;div class="c5 c1"&gt;
&lt;ul&gt;
&lt;li&gt;Only works for inter-project dependencies (which were built by the same build server)&lt;/li&gt;
&lt;li&gt;Not flexible enough
&lt;ul&gt;
&lt;li&gt;Includes/excludes&lt;/li&gt;
&lt;li&gt;Layout changes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="c16"&gt;
&lt;div class="c2 c17"&gt;4&lt;/div&gt;
&lt;/td&gt;
&lt;td class="c11"&gt;
&lt;div class="c1"&gt;&lt;span class="c0"&gt;Use shared dependencies storage, a.k.a. “repository” (FTP, file server, etc.)&lt;/span&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td class="c21"&gt;
&lt;div class="c5 c1"&gt;
&lt;ul&gt;
&lt;li&gt;Use proven build tools&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td class="c18"&gt;
&lt;div class="c5 c1"&gt;
&lt;ul&gt;
&lt;li&gt;Manual repository populating&lt;/li&gt;
&lt;li&gt;Managing the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="c1"&gt;
&lt;p&gt;As you can see, none of the solutions are without the cons.&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;Here comes Artifactory&lt;/h2&gt;
&lt;div class="c1"&gt;&lt;span class="c0"&gt;Artifactory is  a binary repository – built with binaries management in mind in terms of versioning, management, security, and build servers integration.&lt;/span&gt;&lt;/div&gt;
&lt;div class="c1"&gt;&lt;span class="c0"&gt;As such, using Artifactory completely eliminates the cons of the fourth solution. Your build can populate the repository using powerful &lt;/span&gt;&lt;span class="c0 c3"&gt;&lt;a class="c4" href="http://wiki.jfrog.org/confluence/display/RTF/Artifactory's+REST+API"&gt;REST API&lt;/a&gt;&lt;/span&gt;&lt;span class="c0"&gt;. M&lt;/span&gt;&lt;span class="c0"&gt;anagement is easy and streamlined. &lt;/span&gt;&lt;/div&gt;
&lt;div class="c1"&gt;&lt;span class="c0"&gt;But there’s more. By using Artifactory CI integration (for Jenkins, TeamCity and Bamboo), you can also avoid the cons of the third solution listed above. First, you can specify which artifacts you are willing to publish. They will be uploaded to Artifactory in the end of the build. Second, you can specify which dependencies your build needs. They will be downloaded from Artifactory during the run. All this simply by using build server UI.&lt;/span&gt;&lt;/div&gt;
&lt;div class="c1"&gt;&lt;span class="c0"&gt;The&lt;/span&gt;&lt;span class="c0"&gt; &lt;/span&gt;&lt;span class="c0 c24"&gt;Artifactory Jenkins plugin&lt;/span&gt;&lt;span class="c0"&gt;, for example, defines as part of the&lt;/span&gt;&lt;span class="c0"&gt;&lt;a class="c4" href="https://wiki.jenkins-ci.org/display/JENKINS/Artifactory+Plugin#ArtifactoryPlugin-ConfiguringGeneric%28Freestyle%29Builds"&gt; &lt;/a&gt;&lt;/span&gt;&lt;span class="c3 c0"&gt;&lt;a class="c4" href="https://wiki.jenkins-ci.org/display/JENKINS/Artifactory+Plugin#ArtifactoryPlugin-ConfiguringGeneric%28Freestyle%29Builds"&gt;Generic&lt;/a&gt;&lt;/span&gt;&lt;span class="c3 c0"&gt;&lt;a class="c4" href="https://wiki.jenkins-ci.org/display/JENKINS/Artifactory+Plugin#ArtifactoryPlugin-ConfiguringGeneric%28Freestyle%29Builds"&gt; build support&lt;/a&gt;&lt;/span&gt;&lt;span class="c0"&gt;, a simple pattern-based language that allows you to express what artifacts from the build are going to be deployed to the repository. This includes attaching dynamic searchable properties to these artifacts upon deployment. &lt;/span&gt;&lt;/div&gt;
&lt;div class="c1"&gt;&lt;span class="c0"&gt;First, enable Generic-Artifactory Integration in the Build Environment:&lt;/span&gt;&lt;/div&gt;
&lt;div class="c1"&gt;
&lt;div class="separator" style="clear:both;text-align:center;"&gt;&lt;a style="margin-left:1em;margin-right:1em;" href="http://jbaruch.files.wordpress.com/2012/05/configuration.png?w=300"&gt;&lt;img src="http://jbaruch.files.wordpress.com/2012/05/configuration.png?w=300" alt="" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Next, configure your custom deployment and resolution rules. Let&amp;#8217;s start with deployment (publishing):&lt;/p&gt;
&lt;div class="separator" style="clear:both;text-align:center;"&gt;&lt;/div&gt;
&lt;div class="separator" style="clear:both;text-align:center;"&gt;&lt;a style="margin-left:1em;margin-right:1em;" href="http://jbaruch.files.wordpress.com/2012/05/customdeploy.png?w=300"&gt;&lt;img src="http://jbaruch.files.wordpress.com/2012/05/customdeploy.png?w=300" alt="" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class="c0"&gt;In the above example, we configured the following rules for deployment. All the artifacts will be deployed from the working directory into the ‘libs-release-local&amp;#8217; repository (configured above), &lt;/span&gt;&lt;span class="c0"&gt;maintaining &lt;/span&gt;&lt;span class="c0"&gt;the path for each file:&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;table border="1" cellspacing="0" cellpadding="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th width="30%"&gt;Pattern&lt;/th&gt;
&lt;th width="70%"&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;**/x64/*.dll=&amp;gt;x64Win&lt;/td&gt;
&lt;td&gt;Deploys all DLLs to the &amp;#8216;x64Win&amp;#8217; directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;**/*.zip=&amp;gt;winFiles&lt;/td&gt;
&lt;td&gt;Deploys all zip files to the winFiles directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;unix/*.tgz&lt;/td&gt;
&lt;td&gt;Deploys all tgz files under the unix directory to the root directory of the target repository&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
The plugin also controls which artifacts to resolve from the repository before the build starts. The resolution allows you to specify smart search patterns:&lt;/p&gt;
&lt;div class="separator" style="clear:both;text-align:center;"&gt;&lt;a style="margin-left:1em;margin-right:1em;" href="http://jbaruch.files.wordpress.com/2012/05/customresolve.png?w=300"&gt;&lt;img src="http://jbaruch.files.wordpress.com/2012/05/customresolve.png?w=300" alt="" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class="c0"&gt;In the above example, we configured the following rules for dependencies resolution&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;table border="1" cellspacing="0" cellpadding="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th width="30%"&gt;Pattern&lt;/th&gt;
&lt;th width="70%"&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;libs-release-local:x64Wi/*;compatibilityLevel =medium,high&lt;/td&gt;
&lt;td&gt;Resolves the files from the x64Wi directory of the libs-release-local repository to the root of the workspace, but only if the ‘compatibilityLevel&amp;#8217; property is set to be above medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;libs-snapshot-local:*.zip=&amp;gt;winFiles&lt;/td&gt;
&lt;td&gt;Resolves all zip files from libs-snapshot-local repository to winFiles directory under the root of the workspace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;libs-snapshot-local:unix/distro.tgz=&amp;gt;linuxFiles&lt;/td&gt;
&lt;td&gt;Resolves the distro.tgz file from unix directory in libs-snapshot-local to linuxFiles directory under the root of the workspace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;libs-release-local:**/*@winx64_build#released&lt;/td&gt;
&lt;td&gt;This example shows dependency to artifacts produced during an earlier build that has been marked with a &amp;#8220;released&amp;#8221; status&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="c1 c19"&gt;&lt;span class="c0"&gt;&lt;br /&gt;
From a configuration standpoint, this support for automatic dependency declaration and publishing makes it very easy to support a release flow where multiple artifacts are collected towards building the final release&lt;/span&gt;&lt;span class="c0"&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div class="c1"&gt;&lt;span class="c0"&gt;You are more than welcome to give it a try. The publishing functionality described above is available in the &lt;/span&gt;&lt;span class="c3 c0"&gt;&lt;a class="c4" href="http://www.jfrog.com/download.php"&gt;free open source version of Artifactory&lt;/a&gt;&lt;/span&gt;&lt;span class="c0"&gt;. If you want to configure dependencies resolution, go ahead and download the &lt;/span&gt;&lt;span class="c3 c0"&gt;&lt;a class="c4" href="http://www.jfrog.com/addons.php"&gt;Pro version evaluation&lt;/a&gt;&lt;/span&gt;&lt;span class="c0"&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div class="c1"&gt;&lt;span class="c0"&gt;Dependency management is critical for continuous integration and rapid release. By adding Artifactory to your CI stack, you can easily overcome the lack of such functionality in your build tool, leaving the dependency resolution and artifacts deployment to the binary repository and your build server.&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;Resolves the distro.tgz file from unix directory in libs-snapshot-local to linuxFiles directory under the root of the workspace&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;br /&gt;Filed under: &lt;a href='http://blog.sadogursky.com/category/artifactory-2/'&gt;Artifactory&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/category/jfrog/'&gt;JFrog&lt;/a&gt; Tagged: &lt;a href='http://blog.sadogursky.com/tag/net/'&gt;.net&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/artifactory/'&gt;artifactory&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/best-practices/'&gt;best practices&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/build-2/'&gt;build&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/c/'&gt;c&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/continuous-integration/'&gt;continuous integration&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/ios/'&gt;iOS&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/jenkins/'&gt;jenkins&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/native/'&gt;native&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/objective-c/'&gt;objective C&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/pyhton/'&gt;Pyhton&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jbaruch.wordpress.com/243/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jbaruch.wordpress.com/243/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jbaruch.wordpress.com/243/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jbaruch.wordpress.com/243/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jbaruch.wordpress.com/243/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jbaruch.wordpress.com/243/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jbaruch.wordpress.com/243/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jbaruch.wordpress.com/243/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jbaruch.wordpress.com/243/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jbaruch.wordpress.com/243/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jbaruch.wordpress.com/243/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jbaruch.wordpress.com/243/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jbaruch.wordpress.com/243/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jbaruch.wordpress.com/243/" /&gt;&lt;/a&gt; &lt;img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.sadogursky.com&amp;#038;blog=481424&amp;#038;post=243&amp;#038;subd=jbaruch&amp;#038;ref=&amp;#038;feed=1" width="1" height="1" /&gt;</description>
      <pubDate>Thu, 31 May 2012 02:36:00 CDT</pubDate>
      <guid isPermaLink="true">http://blog.sadogursky.com/?p=243</guid>
      <dc:creator>Baruch Sadogursky</dc:creator>
    </item>
    <item>
      <title>The Key Tenets - 7 Years after The Internet Services Disruption</title>
      <link>http://projectautomationexperience.com/blog/ken_sipe/2012/05/the_key_tenets__7_years_after_the_internet_services_disruption</link>
      <description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;October 28 2005 Ray Ozzie, having recently joined Microsoft (msft) at the time, put together an interesting manifesto with the subject title of "&lt;a href="http://scripting.com/disruption/ozzie/TheInternetServicesDisruptio.htm"&gt;The Internet Services Disruption&lt;/a&gt;", with the purpose of "get all of us roughly on the same page". &amp;nbsp;For currently undisclosed reasons, &amp;nbsp;I had reason to review this document and found it completely&amp;nbsp;fascinating. &amp;nbsp;Ray's foresight and ability to forecast the future is just amazing. &amp;nbsp; Although his writing was made public (good for us all), it was intended to inspire and position MSFT for it's next great phase. &amp;nbsp; Let's look at each of the key tenets Ray outlined and see who in our industry has the upper hand.&lt;br /&gt;&lt;br /&gt;1. &amp;nbsp;The power of the advertising-supported model&lt;br /&gt;Is MSFT winning here... definitely not. &amp;nbsp; Winners in this category are Google, making money off google.com. &amp;nbsp; Facebook making money on ads based again on high traffic visitations. &amp;nbsp;While these two companies are making good money with this concept, the company to watch is Apple. &amp;nbsp;Why? &amp;nbsp;Apple is actually empowering developers with this ad-support model through iAd. &amp;nbsp;Like ads or not... Apple is enabling developers to provide solutions free to consumers and are paid through ad hits. &amp;nbsp; &amp;nbsp;There has also been a resent uptick in the number of ads off services like Hulu and youtube. &amp;nbsp; So there is no question that Ray nailed this tenet. &lt;br /&gt;&lt;br /&gt;2. The effectiveness of a new delivery and adoption model&lt;br /&gt;While Ray describes this in a try before you buy, and a readership and review model, &amp;nbsp;while being valid it is&amp;nbsp;ubiquitous, so it is hard to give any one company brownie points for this. &amp;nbsp;Most of the good companies have their share of fan boys, VIP programs and&amp;nbsp;evangelist (in the which MSFT does a stellar good at), &amp;nbsp; I would like to take this concept a little deeper. &amp;nbsp; New delivery... and delivery of what. &amp;nbsp;Considering operating systems and software, everyone is going disc-less. &amp;nbsp;Delivery of updates are internet provided. &amp;nbsp; But lets talk content... There is a new delivery mechanism for content... how do you watch your movies, how to you read your books, how do you get your music? &amp;nbsp; Where is MSFT in this space? &amp;nbsp;No where to be found. &amp;nbsp; Who owns this space? &amp;nbsp;Well... depending it seems divided between Amazon, NetFlix AND the big one? &amp;nbsp;Apple. &amp;nbsp; Apple hits gold stars in this category up and down their product like. &amp;nbsp;In fact one could say that the adoption of an iPod or iPad is a gateway into the full Apple stack.&lt;br /&gt;&lt;br /&gt;3. The demand of compelling, integrated user experiences that "just work"&lt;br /&gt;While I could go into detail and beat around the bush... this statement screams Apple. &amp;nbsp; While apple costs more in some cases, they are uncompromising and focus on the user experience. &amp;nbsp;They have all the advantages in this category as well. &amp;nbsp;they own the full tech stack... they don't have to make it work on a billion devices... they have theirs.&lt;br /&gt;&lt;br /&gt;I consider myself a technologist and I don't "belong" to a specific tech group. &amp;nbsp;I see value in a number of camps. &amp;nbsp; The take away for me... is how insightful Ray was almost 7 years ago. &amp;nbsp;He nailed it. &amp;nbsp;It is too bad that MSFT doesn't seem to be paying attention to him.&amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7461275049781191261-6723194025877692673?l=kensipe.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
      <pubDate>Mon, 28 May 2012 11:49:32 CDT</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-7461275049781191261.post-6723194025877692673</guid>
      <dc:creator>Ken Sipe</dc:creator>
    </item>
    <item>
      <title>The Relaunch</title>
      <link>http://projectautomationexperience.com/blog/matt_stine/2012/05/the_relaunch</link>
      <description>&lt;p&gt;I have rebooted this blog many times over the last several years. If you&amp;#8217;ve been a reader of my blog in the past, you will have noticed significant changes. If you&amp;#8217;re new here, welcome!&lt;/p&gt;

&lt;p&gt;This reboot has been in the works for several months now, even though I&amp;#8217;ve probably spent far less than 24 active hours working on it. Life as an &amp;#8220;itinerant&amp;#8221; consultant and conference speaker is extremely busy compared to what I was doing on May 16, 2012 (the date of my last blog posting). At that time I was in the middle of a transition from 3+ years as a front-line manager of a software development team into a lead software architect role. Since that time I&amp;#8217;ve changed jobs (careers?) twice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;June 2011 - February 2012: During this time I was titled as a &amp;#8220;Technical Architect&amp;#8221; at AutoZone&amp;#8217;s corporate offices in Memphis, TN. My focus was the modernization of their retail store management system architecture and technical stack. While there I also did a fair amount of agile coaching.&lt;/li&gt;
&lt;li&gt;February 2012 - Present: In January, VMware came calling, wanting to know if I would join the vFabric Cloud Application Platform PSO as a Senior Consultant. After a few weeks of interviews and careful consideration, I made the jump. I&amp;#8217;m now in the midst of helping a Fortune 50 company build a brand new &amp;#8220;private cloud&amp;#8221; hosting platform for their next generation of application development.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;During that time I also significantly increased my participation on the No Fluff Just Stuff tour. In other words, I&amp;#8217;ve BEEN BUSY.&lt;/p&gt;

&lt;p&gt;At any rate, I have for quite awhile now wanted to get back into the practice of writing. However, I&amp;#8217;ve wanted to do so outside the constraints of a hosted platform like Blogger or WordPress.com. Those systems place far too many constraints on how your blog works, and they also happen to be the only place that your data is housed. Sure, I could write my posts in Vim and then copy/paste them into the platform, but that&amp;#8217;s annoying. I wanted to manage my writing using a plain text editor, mark it up using something lightweight like Markdown, check my writing into version control using Git, generate my site using a tool like Jekyll, and then push my site to the cloud. What was the easiest way to achieve all of this goodness? &lt;a href="http://octopress.org"&gt;Octopress&lt;/a&gt; seemed to fit the bill.&lt;/p&gt;

&lt;p&gt;So, what you now see is the result of my labor in migrating from WordPress.com to Octopress, hosted at Heroku. One day (perhaps) I&amp;#8217;ll write up the process that I used. It was a bit convoluted and involved gigantic piles of yak hair, so I&amp;#8217;d rather not consider that piece right now.&lt;/p&gt;

&lt;p&gt;What I will be focusing on quite a bit is the idea of simplicity. For more than a decade I have wandered through the barren wasteland that is accidental complexity in software. A few months ago I viewed Rich Hickey’s &lt;a href="https://thestrangeloop.com/sessions/simple-made-easy"&gt;keynote session at StrangeLoop 2011&lt;/a&gt; entitled &lt;a href="http://www.infoq.com/presentations/Simple-Made-Easy"&gt;“Simple Made Easy”&lt;/a&gt;. It is Rich’s definition of simplicity in software that has inspired the brand new title of this blog, wherein I will chronicle my continuing quest to seek out simplicity in software structure.&lt;/p&gt;

&lt;p&gt;Alas, it is time to return to billable work. I shall endeavor to post again in far less than a year. So, as we say in the south, &amp;#8220;Ya&amp;#8217;ll come back now, you hear?&amp;#8221;&lt;/p&gt;</description>
      <pubDate>Thu, 24 May 2012 19:45:00 CDT</pubDate>
      <guid isPermaLink="true">http://mattstine.com/2012/05/24/the-relaunch</guid>
      <dc:creator>Matt Stine</dc:creator>
    </item>
    <item>
      <title>On Using the Right Tool for the Job</title>
      <link>http://projectautomationexperience.com/blog/baruch_sadogursky/2012/05/on_using_the_right_tool_for_the_job</link>
      <description>&lt;h6&gt;Disclaimer: The code samples in the post below are for brain teasing only. Do not, I repeat, do not ever do such things for any other purpose!&lt;/h6&gt;
&lt;p&gt;&lt;a href="http://jbaruch.files.wordpress.com/2012/05/2012-05-22_124729.png"&gt;&lt;img class=" wp-image-232 alignnone" title="counterexample" src="http://jbaruch.files.wordpress.com/2012/05/2012-05-22_124729.png?w=308&amp;h=87" alt="" width="308" height="87" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A friend of mine is a big fan of puzzlers. Any puzzlers, including programming ones. Here&amp;#8217;s his latest and greatest:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Write some code in the static initializer to make the assert pass:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="brush: java;"&gt;
public class Test {
 static {
//Write some code here
 }

public static void main(String[] args) {
 Integer a = 20;
 Integer b = 20;
 assert (a + b == 60);
 }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Don&amp;#8217;t forget to enable assertions if you want to solve this one (-ea as VM parameter).&lt;/p&gt;
&lt;p&gt;If you solved it, or don&amp;#8217;t feel like puzzlers, read on for the solution and the punchline.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-219"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;First, the solution: You need to know refection and two facts about Integers to solve this one:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Integers have cache for all values in range -128 to 127.&lt;/li&gt;
&lt;li&gt;Integers use that cache during auto-boxing (as opposite to using Integer&amp;#8217;s constructor, for example).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Well, you also need to know the exact implementation of the Integer class to figure out where the cache is and what&amp;#8217;s the name, but rt.jar sources are here for the rescue. Guess what? the cache is a private variable inside a private inner class. Joy-joy.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the plan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get Integer&amp;#8217;s class object.&lt;/li&gt;
&lt;li&gt;Get the list of its inner classes.&lt;/li&gt;
&lt;li&gt;Find the right one (what a relief, it only has one. Or not &amp;#8211; it is subject to change in future versions since we are digging in highly encapsulated stuff . Duh.)&lt;/li&gt;
&lt;li&gt;Get the cache field from it.&lt;/li&gt;
&lt;li&gt;It&amp;#8217;s private, set it to accessible in order to get the value of the field.&lt;/li&gt;
&lt;li&gt;Change the value of &amp;#8220;20&amp;#8243; to be &amp;#8220;30&amp;#8243;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;#8217;s the code of the static initializer:&lt;/p&gt;
&lt;p&gt;&lt;pre class="brush: java;"&gt;
 static {
try {
 Class&amp;lt;?&amp;gt;[] declaredClasses = Integer.class.getDeclaredClasses();
 Field cacheField = declaredClasses[0].getDeclaredField(&amp;quot;cache&amp;quot;);
 cacheField.setAccessible(true);
 ((Integer[]) cacheField.get(null))[20 + 128] = 30;
 } catch (Exception e) { e.printStackTrace(); }
 }
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Personally, I hate it. It&amp;#8217;s ugly, it messes with very low-level encapuslated stuff that one even doesn&amp;#8217;t suppose to know, and it is fragile (e.g. it won&amp;#8217;t work if Integer is created with constructor).&lt;/p&gt;
&lt;p&gt;And fairly, we just got lucky. If Integers did not have the cache then we would not  have any way to change what &amp;#8220;+&amp;#8221; does!&lt;/p&gt;
&lt;p&gt;So, why this simple trick is so difficult to impossible to implement? Simple &amp;#8211; Java is not intended for those tricks. Java is static, and it is good! It means that you can rely on it. 20+20 will (almost always) be 40. That is Good.&lt;/p&gt;
&lt;p&gt;If you want to do dynamic stuff, like changing the behavior of  a &amp;#8220;+&amp;#8221; operator, you&amp;#8217;d better use the right tool for the job. E.g. &amp;#8211; Groovy.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the Groovy version of the puzzler:&lt;/p&gt;
&lt;p&gt;&lt;pre class="brush: groovy;"&gt;
//Write some code here
Integer a = 20
Integer b = 20
assert 60 == a + b
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Looks almost the same (without the main() mess, some ridiculous semicolons and the need to include -ea in VM parameters), but the difference in the way to achieve the desired is huge. Since Groovy is dynamic it is intended to do stuff like changing the behavior of the plus sign. Here&amp;#8217;s the facts about Groovy that you need to know to solve this one:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Groovy operates with wrappers, always.&lt;/li&gt;
&lt;li&gt;Groovy implements operators though methods. &amp;#8220;+&amp;#8221; is implemented in plus() method.&lt;/li&gt;
&lt;li&gt;Using Groovy&amp;#8217;s MetaClasses you can easily replace method with any closure.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;#8217;s the plan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get Integer&amp;#8217;s MetaClass.&lt;/li&gt;
&lt;li&gt;Replace plus() method with implementation that returns 60.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&amp;#8217;s all. Really. Here&amp;#8217;s the code:&lt;/p&gt;
&lt;p&gt;&lt;pre class="brush: groovy;"&gt;
Integer.metaClass.plus = {int i -&amp;gt; 60 }
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Nuff said. Now you only have 2 options. Stop doing those ugly tricks, or at least do it with the right tools for the job.&lt;/p&gt;
&lt;br /&gt;Filed under: &lt;a href='http://blog.sadogursky.com/category/development/'&gt;Development&lt;/a&gt; Tagged: &lt;a href='http://blog.sadogursky.com/tag/groovy/'&gt;groovy&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/java/'&gt;java&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/metaclass/'&gt;metaClass&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/reflection/'&gt;reflection&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jbaruch.wordpress.com/219/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jbaruch.wordpress.com/219/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jbaruch.wordpress.com/219/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jbaruch.wordpress.com/219/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jbaruch.wordpress.com/219/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jbaruch.wordpress.com/219/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jbaruch.wordpress.com/219/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jbaruch.wordpress.com/219/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jbaruch.wordpress.com/219/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jbaruch.wordpress.com/219/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jbaruch.wordpress.com/219/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jbaruch.wordpress.com/219/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jbaruch.wordpress.com/219/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jbaruch.wordpress.com/219/" /&gt;&lt;/a&gt; &lt;img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.sadogursky.com&amp;#038;blog=481424&amp;#038;post=219&amp;#038;subd=jbaruch&amp;#038;ref=&amp;#038;feed=1" width="1" height="1" /&gt;</description>
      <pubDate>Mon, 21 May 2012 09:57:00 CDT</pubDate>
      <guid isPermaLink="true">http://blog.sadogursky.com/?p=219</guid>
      <dc:creator>Baruch Sadogursky</dc:creator>
    </item>
    <item>
      <title>Getting the Spock out of a Gradle War</title>
      <link>http://projectautomationexperience.com/blog/ken_sipe/2012/04/getting_the_spock_out_of_a_gradle_war</link>
      <description>I recent ran into a interesting situation, for which I thought it would be worth sharing.   I have a new project with the following build needs:  Java, Spring MVC and &lt;a href="http://code.google.com/p/spock/"&gt;Spock Testing.&lt;/a&gt;  The problem is simple... The WAR build in gradle was building a WAR file that included the Groovy libraries.   This project has no need for groovy at runtime.  &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; is needed because I'm using Spock for my testing.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Gradle and providedCompile&lt;/h3&gt;In older versions of Gradle it was commonly necessary to manage the jars in the lib directory.  In the maven world, there is a dependency scope of "provided".  This scope basically means that the dependency will be provided on the server classpath, however for the purposes of compiling the code in the project it is necessary.  From a WAR perspective it means use this dependency for compile, but do not include it in the lib directory of the WAR.  Gradle within the last year has added the same feature as providedCompile or providedRuntime.  In my project I have this very need with the servlet-api, shown below.&lt;br /&gt;&lt;pre class="brush: groovy"&gt;dependencies {&lt;br /&gt; compile "org.springframework:spring-webmvc:$springVersion"&lt;br /&gt;compile 'javax.servlet:jstl:1.2'&lt;br /&gt; providedCompile 'javax.servlet:servlet-api:2.5' &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;Spock dependencies and Gradle&lt;/h3&gt;As Spock is a groovy testing tool, it is no surprise that Spock requires groovy.   This requires a couple of well documented configurations in your gradle file.  First, you'll have to add the groovy plugin.  Second you have to set as a dependency the groovy version.  But wait!!!  The dependency for groovy doesn't have a scoping ability.  This is area where the "model" of gradle breaks down a little bit IMO.  Ideally you would be interested in expressing in the model that there are "testing" needs... and those testing needs require groovy and spock dependencies.&lt;br /&gt;&lt;pre class="brush: groovy"&gt;apply plugin: 'groovy'&lt;br /&gt;&lt;br /&gt;def spockVersion = '0.5-groovy-1.8'&lt;br /&gt;def springVersion = '3.1.0.RELEASE'&lt;br /&gt;&lt;br /&gt;dependencies { &lt;br /&gt;groovy 'org.codehaus.groovy:groovy-all:1.8.3'&lt;br /&gt; testCompile 'junit:junit:4.8.1'&lt;br /&gt;testCompile "org.spockframework:spock-core:$spockVersion"&lt;br /&gt;testCompile "org.spockframework:spock-spring:$spockVersion"&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;With this groovy dependency any build of WAR will result in a the groovy-all-?.?.?.jar file being added to the the WEB-INF/lib directory.   The problem is I have no current interest in having groovy in production for this project.   What to do?  What to do?&lt;br /&gt;&lt;h3&gt;Gradle Doc to the Rescue&lt;/h3&gt;I find that a large number of people (usually new to gradle) struggle with discovering how to resolve such a problem.   The best starting point for getting to know gradle is the gradle &lt;a href="http://gradle.org/docs/current/userguide/userguide.html"&gt;user guide documentation&lt;/a&gt;, but the best starting point to use as a reference is the gradle &lt;a href="http://gradle.org/docs/current/dsl"&gt;dsl documentation&lt;/a&gt; (&lt;a href="http://gradle.org/docs/current/dsl"&gt;http://gradle.org/docs/current/dsl&lt;/a&gt;).   Hopefully it is obvious that what we want to change is the build of the WAR.  So lets look at the War task.   Here we see all of it's properties... which includes the classpath property.  The documentation for this property clearly states that this property affects the WEB-INF/classes and the WEB-INF/lib.  Diving deeper into that property we see the default behavior which is:&lt;pre class="brush: groovy"&gt;project.configurations.runtime - project.configurations.providedRuntime&lt;br /&gt;&lt;/pre&gt;So our logical solution would be to include a war task configuration for the building of the classpath like this:&lt;pre class="brush: groovy"&gt;war {&lt;br /&gt; classpath = classpath - project.configurations.groovy&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Happy Coding!  and may your builds never fail!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7461275049781191261-4282875782495769753?l=kensipe.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 05 Apr 2012 13:55:28 CDT</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-7461275049781191261.post-4282875782495769753</guid>
      <dc:creator>Ken Sipe</dc:creator>
    </item>
    <item>
      <title>Speak at the 33rd Degree</title>
      <link>http://projectautomationexperience.com/blog/ken_sipe/2012/03/speak_at_the_33rd_degree</link>
      <description>&lt;a href="http://4.bp.blogspot.com/-s4PxZ6NuXiM/T2YbfoCBn6I/AAAAAAAAAwg/zjWy8QOu3a0/s1600/33Degree_2012_Speaker.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 250px; height: 250px;" src="http://4.bp.blogspot.com/-s4PxZ6NuXiM/T2YbfoCBn6I/AAAAAAAAAwg/zjWy8QOu3a0/s320/33Degree_2012_Speaker.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5721290606756601762" /&gt;&lt;/a&gt;&lt;br /&gt;I will be speaking in Poland this month at the 33rd.  It looks like a great conference line up and Krakow is wonderful.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7461275049781191261-4424212608188615471?l=kensipe.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 18 Mar 2012 12:29:46 CDT</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-7461275049781191261.post-4424212608188615471</guid>
      <dc:creator>Ken Sipe</dc:creator>
    </item>
    <item>
      <title>QCon 2012 – Perfect as Everything in London Should Be</title>
      <link>http://projectautomationexperience.com/blog/baruch_sadogursky/2012/03/qcon_2012__perfect_as_everything_in_london_should_be</link>
      <description>&lt;div style="background-attachment:scroll;background-color:#f7f7f1;background-image:none;display:block;height:51px;line-height:15px;min-height:51px;width:95%;border:1px solid #e3e3d1;margin:0 5px 0 0;padding:5px 2px 3px 10px;"&gt;&lt;span style="color:#000000;"&gt;This post was originally posted on &amp;#8216;&lt;a title="From the Frog's Mouth" href="http://blogs.jfrog.org" target="_blank"&gt;From the Frog&amp;#8217;s Mouth&lt;/a&gt;&amp;#8216;.&lt;br /&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;You&amp;#8217;re welcome to comment here or &lt;a title="QCon 2012 - Perfect as Everything in London Should Be" href="http://blogs.jfrog.org/2012/03/qcon-2012-perfect-as-everything-in.html" target="_blank"&gt;there&lt;/a&gt;.&lt;/span&gt;&lt;strong&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;p&gt;It was &lt;a href="http://www.jfrog.com/"&gt;JFrog&lt;/a&gt;&amp;#8216;s second QCon London, and it just gets better. Imagine: even the London weather was perfect, not to mention the sessions, booth traffic, show organization and food (what, you say, good English food? Well, great IndoPak food, at least). Due to high demand by sponsors, the exhibition took place on two floors (as opposed to one floor last year). Our JFrog booth was located in the same place as in 2011. We’re getting used to the place and are looking forward to returning next March!&lt;/p&gt;
&lt;div&gt;&lt;a href="http://qconlondon.com/dl/qcon-london-2012/web/photo/Londonview600x294.jpg"&gt;&lt;img src="http://qconlondon.com/dl/qcon-london-2012/web/photo/Londonview600x294.jpg" alt="" width="640" height="312" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;The speaker panel was extremely impressive, featuring gurus like Martin Fowler, Adrian Cockcroft (the man behind Netflix’ cloud), Dwight Merriman (co-creator of MongoDB), Damien Katz (creator of CouchDB) and Rich Hickey (creator of Clojure).&lt;/p&gt;
&lt;p&gt;The conference started with two training days &amp;#8211; six full-day tutorials each. From my perspective, the most interesting two tutorials were “&lt;a href="http://qconlondon.com/london-2012/presentation/Cloud%20Architecture"&gt;Cloud Architecture&lt;/a&gt;” by Adrian Cockcroft, where he shared the architecture, best practices and decisions behind Netflix’ cloud (which Artifactory is proud to be a part of) and “&lt;a href="http://qconlondon.com/london-2012/presentation/Continuous%20Delivery%20-%20SOLD%20OUT"&gt;Continuous Delivery&lt;/a&gt;” by ThoughtWorks’ Tom Sulston (that’s as close to the roots of the famous &lt;a href="http://www.amazon.com/gp/product/0321601912"&gt;“Continuous Delivery” book&lt;/a&gt; as you can get). For me, the most fascinating thing in the Continuous Delivery process as ThoughtWorks sees it, is that its virtues are exactly the same as we based our &lt;a href="http://qconlondon.com/london-2012/presentation/Cloud%20Architecture"&gt;Artifactory&lt;/a&gt; upon back in 2006: DevOps automation and rapid release cycle. We appreciated the validation of our concept.&lt;/p&gt;
&lt;p&gt;The remaining three days of the week were all-day sessions. It’s impossible to review such a significant number of talks in one blog post, so I’ll concentrate only on the excellent keynote addresses (with one exception).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qconlondon.com/london-2012/presentation/The%20Data%20Panorama"&gt;Martin’s conference-opening keynote speech&lt;/a&gt; was about data. The main feature of modern data is that it is bigger than you think. Polyglot storage in general and various kinds of NoSQL look like the right solution.&lt;/p&gt;
&lt;p&gt;My favorite keynotes are usually the evening ones. A beer in your hand makes any amusing talk even more enjoyable. One named “&lt;a href="http://qconlondon.com/london-2012/presentation/Developers%20Have%20a%20Mental%20Disorder"&gt;Developers Have a Mental Disorder&lt;/a&gt;” I couldn’t miss! Greg Young gave a great show, funny and entertaining, about serious dilemmas in software development that we, the developers, prefer to ignore. The brightest example, of course is the downside of DRY (did you ever think about one?). By removing duplication, we increase coupling, which can be much worse.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://qconlondon.com/london-2012/presentation/Simple%20Made%20Easy"&gt;Thursday morning’s keynote address &lt;/a&gt;was delivered by Rich Hickey. He spoke about the differences between “Simple” and “Easy”. Sounds pretty similar, but in fact they are very far from being the same. Antonyms to the rescue: simple vs. complex, while easy vs. hard. Now it’s clear &amp;#8211; we need to strive to prevent and remove complexity (go simple) without being afraid of the hard. Choosing easiness may end up creating complexity. Things which are easy, but complex, include OOP, mutable state, imperative loops and frameworks (especially ORM). Things which are simple, but not necessarily easy (at least not until you get them), are LISP-ish languages, like Clojure.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://fbcdn-sphotos-a.akamaihd.net/hphotos-ak-ash4/419636_10150618059748962_751098961_9180344_430460510_n.jpg"&gt;&lt;img class="alignright" style="border-color:initial;border-style:initial;border-width:0;" src="https://fbcdn-sphotos-a.akamaihd.net/hphotos-ak-ash4/419636_10150618059748962_751098961_9180344_430460510_n.jpg" alt="" width="320" height="240" border="0" /&gt;&lt;/a&gt;&lt;a href="http://qconlondon.com/london-2012/presentation/Build%20Trust%20in%20Your%20Build%20to%20Deployment%20Flow!"&gt;My session&lt;/a&gt; also took place on Thursday, in relatively small room, about 70 people. I was more than happy to see that it was almost packed. I spoke about building trust in your build process by selecting the right tools for the job (of course, we consider Artifactory as one). I also spoke about the problems of DevOps in the word of Continuous Delivery in the cloud and the rapid release cycle of SaaS applications. I stressed the huge timeshare of binaries in ALM process and the importance of using a tool that really understands binaries to deal with them. That’s exactly the reason why we developed Artifactory.&lt;/p&gt;
&lt;p&gt;Half of my session was dedicated to live demos, which went smoothly, incredible as it may sound. According to the feedback received, my talk was well accepted, and hopefully will be useful to some of the attendants for building easier and more reliable release processes. The Q&amp;amp;A session continued at our booth, where we repeatedly did live demonstrations and received excellent feedback each time. If you want to get a feeling of my talk, &lt;a href="http://www.slideshare.net/jbaruch/build-trust-in-your-buildtodeployment-flow"&gt;here’s the slide-deck&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Friday was the last day of the conference. It started hard with a highly technical keynote address by John Allspaw with a scary name: “&lt;a href="http://qconlondon.com/london-2012/presentation/Resilient%20Response%20In%20Complex%20Systems"&gt;Resilient Response In Complex Systems&lt;/a&gt;”. For someone like me, who doesn’t deal on a daily basis with Disaster Recovery, the session was astonishing. Looking behind the curtain of that kitchen reveals a totally different way of thinking and planning. It may be how individuals and teams have to perform during a disaster (e.g. personal heroism is bad even if successful; it sends the wrong message to the team), or simulating disasters on live production systems (I never could even dare to think about that). The most obvious, but still eye-opening advice that John gave is to learn from successes, not only from failures. It can give us a lot of information and happens much more frequently, no? The only organization with which I am familiar that embraces that technique is the Israeli Air Force.&lt;/p&gt;
&lt;p&gt;To sum up, the conference was great by every measure: technical sessions, attendance, networking, Artifactory exposure, and after-show quality time. Thank you, InfoQ, for this wonderful event in London. QCon was a great starting shot for JFrog’s “&lt;a href="https://www.facebook.com/artifrog/posts/264469456952764"&gt;Busy March&lt;/a&gt;”. You still can catch Fredric and Yoav giving talks on various events in US and Europe.&lt;/p&gt;
&lt;br /&gt;Filed under: &lt;a href='http://blog.sadogursky.com/category/artifactory-2/'&gt;Artifactory&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/category/confereneces/'&gt;Confereneces&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/category/jfrog/'&gt;JFrog&lt;/a&gt; Tagged: &lt;a href='http://blog.sadogursky.com/tag/artifactory/'&gt;artifactory&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/conferences/'&gt;Conferences&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/jfrog-2/'&gt;jfrog&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/qcon/'&gt;QCon&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jbaruch.wordpress.com/207/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jbaruch.wordpress.com/207/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jbaruch.wordpress.com/207/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jbaruch.wordpress.com/207/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jbaruch.wordpress.com/207/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jbaruch.wordpress.com/207/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jbaruch.wordpress.com/207/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jbaruch.wordpress.com/207/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jbaruch.wordpress.com/207/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jbaruch.wordpress.com/207/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jbaruch.wordpress.com/207/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jbaruch.wordpress.com/207/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jbaruch.wordpress.com/207/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jbaruch.wordpress.com/207/" /&gt;&lt;/a&gt; &lt;img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.sadogursky.com&amp;#038;blog=481424&amp;#038;post=207&amp;#038;subd=jbaruch&amp;#038;ref=&amp;#038;feed=1" width="1" height="1" /&gt;</description>
      <pubDate>Fri, 16 Mar 2012 02:17:00 CDT</pubDate>
      <guid isPermaLink="true">http://blog.sadogursky.com/?p=207</guid>
      <dc:creator>Baruch Sadogursky</dc:creator>
    </item>
    <item>
      <title>Agile: getting the standup right!</title>
      <link>http://projectautomationexperience.com/blog/ken_sipe/2012/03/agile_getting_the_standup_right_</link>
      <description>&lt;span&gt;&lt;span style="font-size: 100%;"&gt;The standup meeting as part of an agile discipline at first seems like an easy and obvious activity.  Yet I keep coming across clients and organizations that seem to struggle with getting it right.  It appears that as long as everyone is standing... and we do that everyday... that we can check "standup" off the list.  Just standing up doesn't make it a stand up! (Please repeat that... as often as it takes to get it.)  On top of that... many organizations seem to think that the stand up is for the scrum master or management to get status.   That's not it either!    Here are some warning signs:&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span&gt;Standups take 30 mins or longer&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;People regularly miss the meeting&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;You are always waiting 10 minutes for that one person&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;The PM or Scrum Master is asking clarifying questions&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span&gt;The standup meeting is NOT:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span&gt;Primarily for status (I know that might seem confusing)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;About the position you are in during the meeting&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;About the Scrum Master&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span&gt;Getting the standup right is crucial for a healthy agile team.  It is for and about the team.   Here is the purpose of the standard up:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span&gt;Synergy - It is a point for developers to synchronize their efforts and realize when there is about to be some code thrash.  It is a point to say, "hey joe, I'm about to do task x which is closely related to your task y, lets get together after the standup".&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;Transparency - Everyone knows what is being done, which provides a double check that each person is doing the highest priority tasks and is there anything holding us up.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;Accountability - This the best place to realize that a team mate is struggling.   When you see that Joe has had a 4 hour task for 2 days its time to say "Joe... lets pair on that... lets see if we can knock that out.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span&gt;These purposes come out of the standard questions most agile developers are aware of: "What did I do?", "What am I going to do?" and "is there anything holding me up?".  I know this sounds like status... it's not.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Advice for Scrum Masters&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: Georgia, serif; "&gt;First realize you are not the reason for the standup&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: Georgia, serif; "&gt;Standups are 10-15 mins.. that's it. &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;Do not ask for follow up during the stand up... if something needs to be followed up, follow the person of interests back to their desk and ask them without tying up everyone else's time.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;If it becomes clear that the team needs to meet.. for a design discussion or a big status meeting or... doesn't matter.  It is super important to delineate that as a separate meeting. "Hey I would like to discuss x with everyone after the standup.  Please stick around.".  Then announce "ok, that is the end of the standup, lets discuss x"&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;The best thing you (Scrum Master) can do during the standup is to facilitate.  Do not allow someone to dominate 5 mins of the 10 min standup or elaborate extensively.  The challenge is not to be a jerk about it...   If it is a challenge, then it is something that needs to be discussed in a retro meeting, asking for the teams opinion and possible solutions.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span&gt;A big part of getting agile right is to understand why we do certain things!  It isn't about standing up.  It is about keeping it short and to the point.  It is about getting the benefits listed above out of it.  &lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Good Luck&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7461275049781191261-3397514181810142164?l=kensipe.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
      <pubDate>Wed, 14 Mar 2012 17:51:07 CDT</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-7461275049781191261.post-3397514181810142164</guid>
      <dc:creator>Ken Sipe</dc:creator>
    </item>
    <item>
      <title>Active Resource Spy</title>
      <link>http://projectautomationexperience.com/blog/david_bock/2012/02/active_resource_spy</link>
      <description>&lt;p&gt;I&amp;#39;m doing a lot of work lately using ActiveResource.&amp;#0160; I wanted to get &amp;#39;down to the wire&amp;#39; and see the traffic flowing over http... so a quick google search, and I found an entry I had written in 2008.&amp;#0160; I love it when that happens!&amp;#0160; So I&amp;#39;m reblogging it with a slight change to make it work in Ruby 1.9.&lt;/p&gt;
&lt;p&gt;If you&amp;#39;re using rails, create an initializer name active_resource_spy.rb and drop in this content:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier;"&gt;class ActiveResource::Connection&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160; # Creates new Net::HTTP instance for communication with&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160; # remote service and resources.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160; def http&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160;&amp;#0160;&amp;#0160; http = Net::HTTP.new(@site.host, @site.port)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160;&amp;#0160;&amp;#0160; http.use_ssl = @site.is_a?(URI::HTTPS)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160;&amp;#0160;&amp;#0160; http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160;&amp;#0160;&amp;#0160; http.read_timeout = @timeout if @timeout&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160;&amp;#0160;&amp;#0160; #Here&amp;#39;s the addition that allows you to see the output&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160;&amp;#0160;&amp;#0160; http.set_debug_output $stderr&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160;&amp;#0160;&amp;#0160; return http&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; &amp;#0160; end&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; end&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;All the data that flows over the http connection will be dumped to &lt;span style="font-family: courier new,courier;"&gt;$stderr &lt;/span&gt;(the terminal you started the app in, unless you redirected it).&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 09 Feb 2012 10:42:00 CST</pubDate>
      <guid isPermaLink="true">http://blog.codesherpas.com/on_the_path/2012/02/active-resource-spy.html</guid>
      <dc:creator>David Bock</dc:creator>
    </item>
    <item>
      <title>Dependency Management with .NET – Doing it Right</title>
      <link>http://projectautomationexperience.com/blog/baruch_sadogursky/2012/02/dependency_management_with_net__doing_it_right</link>
      <description>&lt;div style="background-attachment:scroll;background-color:#f7f7f1;background-image:none;display:block;height:51px;line-height:15px;min-height:51px;width:95%;border:1px solid #e3e3d1;margin:0 5px 0 0;padding:5px 2px 3px 10px;"&gt;&lt;span style="color:#000000;"&gt;This post was originally posted on &amp;#8216;&lt;a title="From the Frog's Mouth" href="http://blogs.jfrog.com" target="_blank"&gt;From the Frog&amp;#8217;s Mouth&lt;/a&gt;&amp;#8216;.&lt;br /&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;You&amp;#8217;re welcome to comment here or &lt;a title="Dependency Management with .NET - Doing it Right" href="blogs.jfrog.org/2012/02/dependency-management-with-net-doing-it.html" target="_blank"&gt;there&lt;/a&gt;.&lt;/span&gt;&lt;strong&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;p&gt;The problem of dependency management is neither new nor original, it exists in all development platforms, and .NET is no different.&lt;/p&gt;
&lt;p&gt;Let’s go through different solutions and see how they perform. I’ll list them here in no particular order.&lt;/p&gt;
&lt;h3&gt;&lt;span id="more-168"&gt;&lt;/span&gt;Keeping dependencies in your source control&lt;/h3&gt;
&lt;p&gt;That’s a very popular solution, and for a reason. The benefits are obvious. Here are some of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No setup. You already have your source control in place (hm, I hope you do!). Add \bin directory, and you are fine.&lt;/li&gt;
&lt;li&gt;No learning curve. Developers are used to work with source control.&lt;/li&gt;
&lt;li&gt;Shared. The whole team gets changes and updates from the server as they occur.&lt;/li&gt;
&lt;li&gt;Enterprisy (in a good way). The software is proven, backed up, DRP is done.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sounds good, doesn’t it? So, what’s wrong with it? Only one thing &amp;#8211; source control systems are designed to control, well, sources. As such they aren’t so great in controlling binaries. These are the shortcomings we all encountered during the years of Version Control System usage for dependencies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It isn’t a proxy. VCS can’t download the dependency you need from a central repository when you need one. You need to manually download it and add it to VCS. The history starts from there &amp;#8211; you just lost the  link to the original file. So, you work hard, and on top of it lost information; this repeat itself for each new dependency.&lt;/li&gt;
&lt;li&gt;Versioning mismatch. Source files are versioned by their content. VCSs know how to diff them and understand what changed. Binaries, on the other side, usually versioned by their name. From VCS point of view they are different entries, each one without any version history.&lt;/li&gt;
&lt;li&gt;Some very popular VCSs (like Subversion) can’t obliterate files. That means &amp;#8211; once a file was added, it stay in the repository forever. That’s not a big issue for small source files, but can become quite a pain when it comes to obsolete large binaries.&lt;/li&gt;
&lt;li&gt;Source control knows how to search sources. And, of course, the most important type of search is by content. Searching for binaries is different: what matters there is the location, structure of the file name and, in case of archived artifact, the contents of archive.&lt;/li&gt;
&lt;li&gt;The permissions scheme of VCSs is tailored for versioning sources (again!). For example, there is no override permission. That’s because overriding sources is something we do all the time (that’s what diff is for in VCS) &amp;#8211; it’s the same security level as, let&amp;#8217;s say, adding a new source file. With binaries the situation is very different. While adding new binaries is fine, overriding released binary is something that shouldn’t be done, one should have a special permission for it.&lt;/li&gt;
&lt;li&gt;Distributed VCSs, awesome by themselves, are particularly unsuited for handling big binary files. When cloning a remote repository to your machine &lt;a href="https://twitter.com/#%21/hlship/status/111143638163132417"&gt;you are bringing all the history of all the files in it&lt;/a&gt;. Now just think about all the huge binaries sitting there&amp;#8230;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you see, the conclusion is simple &amp;#8211; we can do better. Let’s try something specialized for binaries.&lt;/p&gt;
&lt;h3&gt;GAC and WebGAC&lt;/h3&gt;
&lt;p&gt;Global Assembly Cache is, on contradictory to VCS ,tailored for storing binaries. It understands versions, prevents conflicts, and generally does a good job being your local dependencies storage. The main problem with GAC is being local, which means &amp;#8211; each and every developer should take the binaries from somewhere and install them in their local GAC. You see the troubles coming in that setup, don’t you? &lt;a href="http://www.lshift.net/blog/2010/02/27/webgac-minding-your-net-dependencies"&gt;WebGAC&lt;/a&gt; to the rescue here. It&amp;#8217;s essentially GAC shared by WebDAV and enables clients to fetch dependencies from the server, simplifying dependencies management for a team. Let’s do our pros/cons math. The benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GAC is good, standard and proven solution for binaries management. It deals well with versions.&lt;/li&gt;
&lt;li&gt;WebGAC is a central binaries repository for a team. Every team member synchronizes with it.&lt;/li&gt;
&lt;li&gt;WebDAV is popular well-known HTTP extension with locking, security management, etc. Working with the Apache WebDAV module is generally straightforward.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s see what won’t work so great with that solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It isn’t a proxy. WebGAC can’t download the dependency you need from a central repository when you need one. You need to manually download it, add it to WebGAC and only then it becomes available to the team. Not only must you work for every version of every dependency needed, the link to the original file is lost.&lt;/li&gt;
&lt;li&gt;No notion of packages. GAC contains single dlls. You install them one by one. But think about NUnit, as an example. It contains about dozen of dlls along with various xml and configuration files. How can you install it to GAC?&lt;/li&gt;
&lt;li&gt;Security is cumbersome. You’ll need to configure Apache Server’s security, and even then it won’t be flexible enough to determine between deployer (a user that can publish private dependencies) and promoter (a user that can move dependencies from a private repository to a public one).&lt;/li&gt;
&lt;li&gt;Search is basic. WebDAV by itself only knows about files. It doesn’t care about the structure of the filename, or about the presence of Strong Names.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Looks like we still didn’t find what we are looking for, and then&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Here comes NuGet&lt;/h3&gt;
&lt;p&gt;This is something else. &lt;a href="http://nuget.codeplex.com/"&gt;NuGet&lt;/a&gt; designed to be “a developer focused package management system for the .NET platform intent on simplifying the process of incorporating third-party libraries into a .NET application during development”. That’s exactly what we need. Let’s look how great it is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manages packages, not dlls.&lt;/li&gt;
&lt;li&gt;Provides &lt;a href="http://nuget.org/packages"&gt;NuGet Gallery&lt;/a&gt; &amp;#8211; almost 4.5K (at the time of writing) packages are at your disposal for all your development needs.&lt;/li&gt;
&lt;li&gt;Supports binary versioning.&lt;/li&gt;
&lt;li&gt;Integrates with Visual Studio.&lt;/li&gt;
&lt;li&gt;Integrates with your build.&lt;/li&gt;
&lt;li&gt;Integrates with your build server (only &lt;a href="http://blogs.jetbrains.com/dotnet/2011/08/native-nuget-support-in-teamcity/"&gt;TeamCity&lt;/a&gt; at the moment of writing).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This tool&amp;#8217;s like a dream come true. So, what can I mention as downsides? Most of them are downsides of the NuGet Gallery, not NuGet itself. The Gallery is a young and relatively small project (just for the sake of comparison, Maven Central is 6 years old and contains more than 290K artifacts) and, as such, it has its downsides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The content of submissions to the Gallery is (almost) unverified. Everyone can register, get the API key and start uploading whatever they like. Scary, isn&amp;#8217;t it? (yes, very scary).&lt;/li&gt;
&lt;li&gt;Being public, NuGet Gallery can’t be used for inter-team packages exchange. &lt;a href="http://docs.nuget.org/docs/creating-packages/hosting-your-own-nuget-feeds#Creating_Remote_Feeds"&gt;Private Remote Feeds&lt;/a&gt; are the recommended solution. Next we&amp;#8217;ll see if it is good enough.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Working with NuGet Remote Feeds&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://docs.nuget.org/docs/creating-packages/hosting-your-own-nuget-feeds#Creating_Remote_Feeds"&gt;Remote Feeds&lt;/a&gt;, introduced in NuGet 1.4 are crucial need for any development team. It serves a dual purpose: it allows sharing 3rd party packages that aren’t available on Gallery (or even replaces the Gallery for those who can’t trust it) and it serves as a target for internal deployments &amp;#8211; both for team collaboration and for other usages, as making packages available to QA, or even serving them to the customers from the outside world (by using &lt;a href="http://chocolatey.org/"&gt;Chocolatey&lt;/a&gt;, for example). If that’s so right, what’s wrong? Here’s what:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You saw it coming: It isn’t a proxy. You know the score by now.&lt;/li&gt;
&lt;li&gt;It can’t aggregate. The NuGet Remote Feed exposing one monolithic repository: the one you have on your machine. It can’t aggregate NuGet packages from remote repositories, or expose number of local repositories (separated for security reasons, for example).&lt;/li&gt;
&lt;li&gt;You can’t attach your own metadata. Let’s say you want to annotate some package with compatibility information (e.g. works with certain browsers). No, can’t do.&lt;/li&gt;
&lt;li&gt;The repository is very simplistic. It doesn’t provide any web interface; it browsable and searchable only from a client &amp;#8211; be it Visual Studio or the command line interface (pretty basic by itself).&lt;/li&gt;
&lt;li&gt;Even the VS search interface is very basic (all you have is arbitrary sorting and free text search). It should be enough for starters but lack of searching inside the packages or by properties (from the previous bullet) will bite you eventually.&lt;/li&gt;
&lt;li&gt;The security scheme is even less than simplistic. All that&amp;#8217;s required to authenticate a deployment/delete of all the users at once is an API key. What about separation of duties? Some users should only be able to read, others only to annotate with metadata (QA team that tests compatibility in my previous example), and only small subgroup &amp;#8211; to deploy.  The all-or-nothing scheme is definitely insufficient.&lt;/li&gt;
&lt;li&gt;Storage format is suboptimal:
&lt;ul&gt;
&lt;li&gt;The packages are stored on the filesystem in a naive simple format. That fine for small repository,but as you grow, you&amp;#8217;d expect storage which more optimized for binaries.&lt;/li&gt;
&lt;li&gt;The metadata is not indexed. Again, fine for small repo, troubles are foreseen when it comes to scaling.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, is there a good alternative to NuGet Remote Feed to be your in-house Gallery for NuGet packages? We, the proud makers of &lt;a href="http://www.jfrog.com/"&gt;Artifactory&lt;/a&gt;,  believe there is.&lt;/p&gt;
&lt;h3&gt;Meet Artifactory&lt;/h3&gt;
&lt;p&gt;&lt;a id="internal-source-marker_0.8537193675811334" href="http://www.jfrog.com/"&gt;Artifactory&lt;/a&gt; is an enterprise-grade Binary Repository that centralizes all aspects of managing software binaries. That means that we tackle all the problems mentioned above. We are developing Artifactory since 2006. Being used by millions of users for storing, sharing and managing binaries, we have gathered great feedback from our users.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s what we&amp;#8217;ve learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Binary packages are different from sources (by being big and binary) and deserve smart storage.&lt;/li&gt;
&lt;li&gt;Binary packages are usually archives (be it jars, zips, rpms or nupkgs). They should be browsable and searchable without the need to download them locally to developer&amp;#8217;s machine.&lt;/li&gt;
&lt;li&gt;Big public repositories exist on the net, they need to be proxied smartly (variations, auditing, managing)&lt;/li&gt;
&lt;li&gt;Users come in different flavors. Their permissions should match possible responsibilities (and in the case of binary packages they are different from other cases).&lt;/li&gt;
&lt;li&gt;A binary repository holds critical information, it should be rock-solid, backed up, and DRP ready.&lt;/li&gt;
&lt;li&gt;Your software ends up being a package. We know how to help you&amp;#8230;
&lt;ul&gt;
&lt;li&gt;build it in a reproducible manner, integrating with your build tools and your build server.&lt;/li&gt;
&lt;li&gt;stage it to ensure the best quality.&lt;/li&gt;
&lt;li&gt;distribute it to your customers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You get the gist behind Artifactory by watching this 2.5 minutes video: &lt;span style="text-align:center; display: block;"&gt;&lt;a href="http://blog.sadogursky.com/2012/02/06/dependency-management-with-net-doing-it-right/"&gt;&lt;img src="http://img.youtube.com/vi/aa4YBDUDWy0/2.jpg" alt="" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;
If you’re not in the mood for movies (or ran out of popcorn), here’s quick recap:&lt;a href="http://jbaruch.files.wordpress.com/2012/02/nuget-poxy.png"&gt;&lt;img class="size-full wp-image-196 aligncenter" title="Artifactory" src="http://jbaruch.files.wordpress.com/2012/02/nuget-poxy.png?w=700&amp;h=181" alt="" width="700" height="181" /&gt;&lt;/a&gt;&lt;br /&gt;
As you see, instead of working with a number of NuGet Feeds (NuGet Gallery, Orchard Gallery,  Remote Feeds from co-workers and from different teams) developers work with exactly one repository. It simplifies setup and daily work and centralizes management and maintenance.&lt;br /&gt;
The work is bi-directional, the users resolve their 3rd party dependencies from Artifactory and deploy their created packaged into it.&lt;/p&gt;
&lt;p&gt;Now let’s add a build server to the picture (literally):&lt;a href="http://jbaruch.files.wordpress.com/2012/02/nuget-build.png"&gt;&lt;img class="size-full wp-image-197 aligncenter" title="CI" src="http://jbaruch.files.wordpress.com/2012/02/nuget-build.png?w=700&amp;h=322" alt="" width="700" height="322" /&gt;&lt;/a&gt;&lt;br /&gt;
Yup, with numbers this time. So, here we go:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Developers find and  fetch new 3rd party packages from Artifactory in Visual Studio. The packages are downloaded from Artifactory to the developer&amp;#8217;s machine. If the packages aren’t present in Artifactory it will look for them in remote galleries/feeds. On developer machines &lt;code&gt;packages.config&lt;/code&gt; is updated with the list of used packages.&lt;/li&gt;
&lt;li&gt;Developers commit their code and &lt;code&gt;packages.config&lt;/code&gt; (but not the binaries) to VCS.&lt;/li&gt;
&lt;li&gt;The Build server (as I already mentioned, &lt;a href="http://blogs.jetbrains.com/dotnet/2011/08/native-nuget-support-in-teamcity/"&gt;TeamCity&lt;/a&gt; now supports NuGet) takes the changes from the VCS.&lt;/li&gt;
&lt;li&gt;It builds the solution and packs the produced artifacts as NuGet packages.&lt;/li&gt;
&lt;li&gt;During the build it fetches the needed packages from Artifactory. If the packages aren’t present in Artifactory it will look for them in remote galleries/feeds.&lt;/li&gt;
&lt;li&gt;Once the packages are built they are deployed to Artifactory.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Built packages in Artifactory can be used by other teams (as their 3rd party dependencies), by QA for running tests and even by the end users (&lt;a href="http://chocolatey.org/"&gt;Chocolatey&lt;/a&gt; FTW), all this with fine-grained permissions and robust promotion procedures (moving a package between repositories with different visibility rules).&lt;br /&gt;
You know what? It deserves dedicated how-to blog post. I’ll link it here once published.&lt;/p&gt;
&lt;p&gt;Assuming you&amp;#8217;ve read up to this point, you&amp;#8217;ve gathered that starting from Artifactory version 2.5.0 we are proud to serve the .NET world with full NuGet support. We can proxy any remote NuGet feed (starting with NuGet Gallery, of course), we can host the packages that aren’t found on any remote NuGet feed, we can host the packages you produce and we can aggregate any number of repositories of any kind under single a URL. We provide you with an awesome UI for configuring your repositories, browsing and searching for your packages. We also feature smart storage that enables attaching searchable metadata on top of your binaries. We can do it all on the cloud with our &lt;a href="https://secure.artifactoryonline.com/art-online.php"&gt;SAAS version&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hopefully , you&amp;#8217;re convinced by now and probably looking for the download link on our site (&lt;a href="https://secure.artifactoryonline.com/addons.php"&gt;here’s it&lt;/a&gt;, BTW, click on “Evalution”). If not, give it a try by playing with &lt;a href="http://repo.jfrog.org/artifactory/webapp/browserepo.html?pathId=nuget-gallery-cache:"&gt;our live demo&lt;/a&gt;. Look at the nuget-gallery cache: that’s how we proxy the NuGet Gallery. You’ll find some of the packages saved locally; once you&amp;#8217;ve selected a package, you’ll see all kinds of information about it: its name and size, who deployed it to Artifactory, where it came from (from NuGet Gallery, naturally for this is the NuGet Gallery cache) and the operations you can perform on this package (as anonymous the selection is naturally limited). Clicking on the triangle in the tree will open the package and let you dive into its content, including downloading specific files from the archive (click for full-size image):&lt;a href="http://jbaruch.files.wordpress.com/2012/02/browse-nupkg.png"&gt;&lt;img class=" wp-image-183 aligncenter" title="Browse Artifactory" src="http://jbaruch.files.wordpress.com/2012/02/browse-nupkg.png?w=548&amp;h=378" alt="Browse Artifactory" width="548" height="378" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We, at JFrog, believe that Artifactory is the missing piece of the puzzle for a robust, agile .NET dependency management, which can make the development process easier compared to other alternatives.&lt;br /&gt;
We&amp;#8217;ll be happy to receive any insights, thoughts and comments on the ideas presented in this blog and/or your experience using Artifactory together with NuGet.&lt;/p&gt;
&lt;br /&gt;Filed under: &lt;a href='http://blog.sadogursky.com/category/artifactory-2/'&gt;Artifactory&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/category/jfrog/'&gt;JFrog&lt;/a&gt; Tagged: &lt;a href='http://blog.sadogursky.com/tag/artifactory/'&gt;artifactory&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/jfrog-2/'&gt;jfrog&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/nuget/'&gt;nuget&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/teamcity/'&gt;teamcity&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jbaruch.wordpress.com/168/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jbaruch.wordpress.com/168/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jbaruch.wordpress.com/168/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jbaruch.wordpress.com/168/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jbaruch.wordpress.com/168/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jbaruch.wordpress.com/168/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jbaruch.wordpress.com/168/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jbaruch.wordpress.com/168/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jbaruch.wordpress.com/168/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jbaruch.wordpress.com/168/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jbaruch.wordpress.com/168/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jbaruch.wordpress.com/168/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jbaruch.wordpress.com/168/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jbaruch.wordpress.com/168/" /&gt;&lt;/a&gt; &lt;img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.sadogursky.com&amp;#038;blog=481424&amp;#038;post=168&amp;#038;subd=jbaruch&amp;#038;ref=&amp;#038;feed=1" width="1" height="1" /&gt;</description>
      <pubDate>Mon, 06 Feb 2012 05:39:00 CST</pubDate>
      <guid isPermaLink="true">http://jbaruch.wordpress.com/?p=168</guid>
      <dc:creator>Baruch Sadogursky</dc:creator>
    </item>
    <item>
      <title>MVC meet JavaScript, JavaScript meet MVC</title>
      <link>http://projectautomationexperience.com/blog/brian_sam-bodden/2011/12/mvc_meet_javascript_javascript_meet_mvc</link>
      <description>&lt;p&gt;&lt;em&gt;For years the software community has been pushing the MVC architectural pattern to organize and separate the concerns of our applications. So far we seem to have done a decent job of accomplishing that based on the enforcement of the pattern in the most successful web frameworks such as Rails, Grails, JSF, Struts and many others. The last frontier for MVC seems to be the sometimes convoluted world of JavaScript; the client tier of our web applications. Although frameworks like jQuery, Prototype, Scriptaculous, ExtJS, DOJO and others have greatly helped in cleaning up and structuring the client tier, there's still much to be desired. In recent years several micro-frameworks have appeared that aim to put an end to the madness of the JavaScript client tier world. In this article we'll explore the most prominent players and see how their usage impacts modern web development.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;Blurting out a solution when so many do not understand the problem would not help. So, let’s start at the beginning… Before the web, but not that long ago, we had client-server applications in which the client was typically a desktop application and the server was a monolithic application that babysat a database. In those days, mastery of programming environments like Delphi, Visual Basic, Powerbuilder and Oracle Forms was in hot demand. Visual component environments allowed, to an extent, the separation of presentation logic from the database. I lived through that period and I remember the feeling that the user interface portions of the application seemed pretty orderly via the use of components but the server side was a disaster. &lt;/p&gt;
&lt;p&gt;Then along came the web and, overwhelmed by the new environment, protocols, and stateless nature of the new beast, we somehow forgot everything we’ve learned in the past. The first applications were monolithic messes both in the front-end and the back (remember CGI scripts?). Then eventually we came to our senses and a myriad of web frameworks started to appear. Most of the frameworks implemented a version of the Model-View-Controller (MVC) pattern.&lt;/p&gt;
&lt;p&gt;So while things got better at the web server level, the UI remained the wild frontier of web development, where JavaScript was the lingua franca and not many could speak it. JavaScript, an amazingly powerful but misused and misunderstood language, was caught smack in the middle of the so-called browser wars. These wars were centered around the differences and inconsistencies on the browser’s DOM (Document Object Model), which also made for a mess at development time. Slowly, the community reacted by creating frameworks like jQuery, Scriptaculous, Prototype, MooTools, Dojo, Ext JS and others that could hide the warts of the DOM implementations (and also mask some of the ugly parts of JavaScript).&lt;/p&gt;
&lt;p&gt;These frameworks have simplified the way we deal with the DOM and JavaScript. They’ve given us the ability to encapsulate visual aspects of the DOM and deal with events in a uniform fashion. But in spite of our best efforts, complex client-side functionality still gets messy very fast. Applications typically end up as a spaghetti mess of callbacks between the DOM, your code and the server-side application. A more structured approach to building rich JavaScript applications is needed.&lt;/p&gt;
&lt;h2 class="fancy"&gt;Model-View-Controller&lt;/h2&gt;
&lt;p&gt;The MVC pattern made its first appearance in 1979 when Trygve Reenskaug described a new architecture for developing interactive applications while working on Smalltalk at Xerox PARC. MVC breaks a functional slice of an application into three basic components: models, views and controllers.&lt;/p&gt;
&lt;p&gt;In the MVC world, the model is responsible for maintaining an aspect of the state of the application. This “state” could be transient, lasting only while dealing with an interaction with the user or persistent and stored outside of the application’s realm. The model is responsible for encapsulating the operations relevant to the entity it represents. This encapsulation carries with it the responsibility of maintaining the integrity of the data that represents the state of the model.&lt;/p&gt;
&lt;p&gt;The view encompasses a user interface element that typically reflects the state of the underlying model. Finally, the controller handles input events from the UI and determines a set of operations to be performed upon the model. Changes to the state of the model are then reflected on the view. How coupled the components of the MVC triumvirate are depends on implementation specific decisions.&lt;/p&gt;
&lt;h2&gt;A Simple Example: A Shopping Cart&lt;/h2&gt;
&lt;p&gt;To illustrate the problems the new breed of MVC frameworks aim to solve, I will first build a dynamic single page JavaScript application without them; a simple drag-n-drop jQuery based shopping cart.&lt;/p&gt;
&lt;p&gt;&lt;img src="/system/images/BAhbB1sHOgZmSSIzMjAxMS8xMi8yNi8wOC8yMy8xNS85NTAvRmlndXJlX1NwaW5lX0JTQl8xLnBuZwY6BkVUWwg6BnA6CnRodW1iSSINNDUweDQ1MD4GOwZU/Figure_Spine_BSB_1.png" title="Figure Spine Bsb 1" alt="Figure Spine Bsb 1" rel="450x450" height="205" width="180" /&gt;&lt;br /&gt;Figure BSB-1 – jQuery Shopping Cart Project&lt;/p&gt;
&lt;p&gt;As shown in Figure BSB-1 the project consists of an HTML page called shopping_cart.html which uses the JavaScript files integrallis.commerce.js and integrallis.jquery.cart.js. These files are an attempt to separate the business objects from the visual aspects of the application. In integrallis.commerce.js I’ve implemented a simple shopping cart as shown in Listing BSB-1 (the full listing for this example can be found at https://github.com/bsbodden/jquery-shopping-cart)&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;var INTEGRALLIS = {};
INTEGRALLIS.commerce = {};

INTEGRALLIS.commerce.ShoppingCart = function(options) {
	// initializes the cart
	this.items = {};
	
	// callbacks
	var defaults = {
		removeAll: function() {},
		updateTotal: function() {},
       	updateItemQuantity: function() {},
       	removeItem: function() {}
	};
	
	// merge options with defaults
	for (property in defaults) { 
		if (!options.hasOwnProperty(property)) { 
			options[property] = defaults[property]
		} 
	}
	
	this.options = options;
}

// removes all items from the cart
INTEGRALLIS.commerce.ShoppingCart.prototype.clear = function() {
	this.items = {};
	this.options.removeAll();
	this.options.updateTotal();
}

// returns the value of all items in the cart
INTEGRALLIS.commerce.ShoppingCart.prototype.total = function() {
	var sum = 0.0;
	for (var index in this.items) {
		var item = this.items[index];
		sum = sum + (item.price * item.quantity);
	}
	return sum;
}

// returns the number of unique items in the cart
INTEGRALLIS.commerce.ShoppingCart.prototype.itemsCount = function() {
	var size = 0, key;
    for (key in this.items) {
        if (this.items.hasOwnProperty(key)) size++;
    }

	return size;
}

// returns whether the cart is empty or not
INTEGRALLIS.commerce.ShoppingCart.prototype.isEmpty = function() {
	return this.itemsCount() == 0;
}
	
// adds a new item to the cart or increases the quantity of an existing item
INTEGRALLIS.commerce.ShoppingCart.prototype.add = function(id, price, quantity) {
	var is_new;
	quantity = (typeof(quantity) != 'undefined') ? quantity : 1;
	if (this.items.hasOwnProperty(id)) {
		var item = this.items[id];
		item.quantity = item.quantity + quantity;
		this.options.updateItemQuantity(id);
		this.options.updateTotal();
		is_new = false;
	}
	else {
	    this.items[id] = { quantity : quantity, price : price };
	    this.options.updateTotal();
	    is_new = true;
    }
    return is_new;
}
		
// increases the quantity of an item in the cart
INTEGRALLIS.commerce.ShoppingCart.prototype.increase = function(id, quantity) {
	quantity = (typeof(quantity) != 'undefined') ? quantity : 1;
	if (this.items.hasOwnProperty(id)) {
		var item = this.items[id];
		item.quantity = item.quantity + quantity;
		this.options.updateItemQuantity(id);
		this.options.updateTotal();
	}
}
		
// decreases the quantity of an item in the cart
INTEGRALLIS.commerce.ShoppingCart.prototype.decrease = function(id, quantity) {
	quantity = (typeof(quantity) != 'undefined') ? quantity : 1;
	if (this.items.hasOwnProperty(id)) {
		var item = this.items[id];
		if (item.quantity &amp;gt;= quantity) {
		    item.quantity = item.quantity - quantity;
	    }
	    else {
		    item.quantity = 0;
	    }
		this.options.updateItemQuantity(id);
		if (item.quantity == 0) {
			delete this.items[id];
			this.options.removeItem(id);
		}
		this.options.updateTotal();
	}
}
		
// returns the quantity of an item in the cart
INTEGRALLIS.commerce.ShoppingCart.prototype.quantityFor = function(id) {
	return this.items.hasOwnProperty(id) ? this.items[id].quantity : 0;
} 
&lt;/pre&gt;
&lt;p&gt;Listing BSB-1&lt;/p&gt;
&lt;p&gt;The shopping cart provides the ability to maintain a list of items and their associated quantities as well as their total value. In order to reflect changes to the cart, I’ve created a set of callback functions (initialized to no-op functions) in the Constructor function of the cart. In integrallis.jquery.cart.js shown in Listing BOD-2, I wire the shopping cart object to the shopping_cart.html page. I start by instantiating the cart and passing the shopping cart UI callback functions. The callbacks use jQuery to update elements of the page to reflect changes in the shopping cart. &lt;/p&gt;
&lt;p&gt;Interaction with the cart will occur when the user drops an HTML element representing an item into the cart “drop” area. To accomplish the drag-n-drop functionality I’m using jQuery’s draggable and droppable functions to enable the elements with class “product” to be dragged and dropped into the element with id “cart”.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;// create a shopping cart instance, set all callbacks
var myShoppingCart = new INTEGRALLIS.commerce.ShoppingCart({ removeItem : removeItem,
	                                                         removeAll : removeAll,
	                                                         updateTotal : updateCartTotal,
	                                                         updateItemQuantity : updateItemQuantity });
	
// shopping cart UI callbacks

function updateItemQuantity(id) {
	$('#cart #' + id)
	    .children('#qty')
	    .text(myShoppingCart.quantityFor(id))
	    .effect("highlight", {}, 1500);		
}

function updateCartTotal() {
	$('#total').text(myShoppingCart.total()).effect("highlight", {}, 1500);
}

function removeItem(id) {
	$('#cart #' + id).effect("puff", {}, "slow", function(){ $(this).remove(); });
}

function removeAll() {
	$('#cart .product').effect("puff", {}, "slow", function(){ $('#cart').empty(); });
}

function decorateForCart(item, id) {
	   item.append(' (&lt;span id="qty"&gt;1&lt;/span&gt;)')
           .append(' &lt;a href="#" id="add"&gt;+&lt;/a&gt;')
           .append(' &lt;a href="#" id="remove"&gt;-&lt;/a&gt;');
       item.children('#add').click(function() {
	       myShoppingCart.increase(id);
       });
       item.children('#remove').click(function() {
	       myShoppingCart.decrease(id);
       });
}

$(document).ready(function() {
	// make products draggable
	$(".product").draggable({ helper: 'clone', opacity: "0.5" });
	
	// allow products to be dropped in the cart
	$("#cart").droppable({ accept: '.product', 
	                       drop: function(ev, ui) {
						       var item_dropped = ui.draggable;
						       var id = item_dropped.attr('id');
					           var price = item_dropped.attr('price');	      
						       if (myShoppingCart.add(id, price)) {
							       var item = item_dropped.clone();
							       decorateForCart(item, id);
							       $(this).append(item);
						       }
		                   }
	});
	
	// jquery-fy the 'clear shopping cart' button
	$('#dump').button().click(function() { myShoppingCart.clear() });
});&lt;/pre&gt;
&lt;p&gt;Listing BSB-2
&lt;/p&gt;
&lt;p&gt;Finally to put the cart to the test in shopping_cart.html where I provide a div representing the shopping cart and a list of “products” that can be dropped into the cart (Listing BOD-3). The “data” for the products is taken from the attributes of the &amp;lt;li&amp;gt; “product” elements.&lt;/p&gt;
&lt;pre class="brush: html;"&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;link href='http://fonts.googleapis.com/css?family=Muli' rel='stylesheet' type='text/css'&amp;gt;
    &amp;lt;link type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/cupertino/jquery-ui.css" rel="stylesheet" /&amp;gt;
    &amp;lt;link type="text/css" href="styles/shopping_cart.css" rel="stylesheet" /&amp;gt;
    
    &amp;lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="src/integrallis.commerce.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="src/integrallis.jquery.cart.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h2&amp;gt;jQuery Shopping Cart&amp;lt;/h2&amp;gt;

    &amp;lt;h3&amp;gt;Available Products&amp;lt;/h3&amp;gt;
    
    &amp;lt;ul class="products" id="products"&amp;gt;
        &amp;lt;li class="product ui-state-default" id="item_0" price="100.0"&amp;gt;Product 0 - $100&amp;lt;/li&amp;gt;
        &amp;lt;li class="product ui-state-default" id="item_1" price="110.0"&amp;gt;Product 1 - $110&amp;lt;/li&amp;gt;
        &amp;lt;li class="product ui-state-default" id="item_2" price="120.0"&amp;gt;Product 2 - $120&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;

    &amp;lt;h3&amp;gt;Your Shopping Cart&amp;lt;/h3&amp;gt;

    &amp;lt;div id="cart"&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;p&amp;gt;Total: $&amp;lt;span id="total"&amp;gt;0.00&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;button id="dump"&amp;gt;Dump the cart!&amp;lt;/button&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Listing BSB-3&lt;/p&gt;
&lt;p&gt;As the elements are dropped into the cart they are cloned and decorated with a couple of links to increase/decrease the quantity of the particular item in the cart.&lt;/p&gt;
&lt;p&gt;In the callbacks we are dealing with dynamically updating the total value of the cart and increasing and decreasing the displayed quantities of an item. Also notice that if we drop an item that already exists in the cart, rather than creating a new item we simply increase the quantity of the existing item. Similarly, when an item’s quantity reaches zero we remove the item from the cart. All these operations are performed with jQuery’s animation capabilities to keep the user aware of changes to the cart.&lt;/p&gt;

&lt;p&gt;&lt;img src="/system/images/BAhbBlsHOgZmSSI8MjAxMS8xMi8yNy8wOS80MC8zMC84OTAvRmlndXJlX1NwaW5lX0JTQl8yX3RyYW5zX3NtLnBuZwY6BkVU/Figure_Spine_BSB_2_trans_sm.png" title="Figure Spine Bsb 2 Trans Sm" alt="Figure Spine Bsb 2 Trans Sm" rel="225x255" height="217" width="900" /&gt;&lt;/p&gt;
&lt;p&gt;Figure BSB-2 – jQuery Shopping Cart in Action&lt;/p&gt;
&lt;h3&gt;Shortcomings of the jQuery Shopping Cart&lt;/h3&gt;
&lt;p&gt;I am obviously taking some shortcuts for the sake of the example such as assuming that the available products magically appeared in the page (in a real application they would be retrieved from a server). But other than that, at first glance the implementation of the shopping cart seems to work as advertised and even seems well thought-out. That is, until we start asking the hard questions…&lt;/p&gt;
&lt;p&gt;From the usability point of view, the first thing that jumps to mind is, what happens when the user clicks the refresh button? Since everything is just being kept in memory the answer is that it simply goes away. The user will end up with an empty shopping cart. The same applies to the back button; both will have the effect of dumping the cart!&lt;/p&gt;
&lt;p&gt;One of the features that simple page applications try to achieve is the minimization of round trips to the server. Since the page is not to be refreshed by the user actions on the page, AJAX calls will have to be made to send the state of the cart back for the server for storage.&lt;/p&gt;
&lt;p&gt;On the code organization front, even though I have taken steps to separate the business logic from the UI interaction code it is still obvious that for anything more complex we would end up with an unmanageable mess of UI callbacks all of which are currently living in the global JavaScript scope.&lt;/p&gt;
&lt;p&gt;Another glaring problem is the coupling of the concepts of the shopping cart and the items in the shopping cart. The items are simple JavaScript objects with no behavior.  Their reflection on the UI is controlled by the decorateForCart function as shown in Listing BSB-2. Ideally our cart items would be good object-oriented citizens and encapsulate both data and behavior.&lt;/p&gt;
&lt;p&gt;Although it might seem that I’m being nitpicky about this implementation, the small issues above are representative of the types of problems that can rapidly turn a JavaScript application into an unbearable mess.&lt;/p&gt;
&lt;h2 class="fancy"&gt;MVC to the Rescue: Introducing Spine&lt;/h2&gt;
&lt;p&gt;Spine is one of the many lightweight JavaScript micro MVC framework choices that have popped into the scene.&lt;/p&gt;
&lt;p&gt;From the Spine Website:&lt;/p&gt;
&lt;div class="et-box et-shadow"&gt;
&lt;p&gt;
"The library is written in CoffeeScript, but doesn't necessarily require CoffeeScript to develop applications. You can use CoffeeScript or JavaScript, whichever language you're most familiar with. Spine is tiny, the library comes in at around 500 lines of CoffeeScript, that's about 2K minified &amp;amp; compressed. Being lightweight and simple is fundamental to Spine."
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Spine’s take on the MVC pattern might be slightly confusing for those accustomed to more traditional MVC implementations. Spine only provides Models and Controllers. &lt;/p&gt;
&lt;p&gt;Figure BSB-3 shows the typical directory structure used for a Spine application. The application consists of 1 model, 2 controllers and a JavaScript file to bootstrap the application.&lt;/p&gt;
&lt;p&gt;&lt;img src="/system/images/BAhbBlsHOgZmSSIyMjAxMS8xMi8yNi8wOC8yMy8xNi8zOC9GaWd1cmVfU3BpbmVfQlNCXzMucG5nBjoGRVQ/Figure_Spine_BSB_3.png" title="Figure Spine Bsb 3" alt="Figure Spine Bsb 3" rel="225x255" height="129" width="185" /&gt;&lt;/p&gt;
&lt;p&gt;Figure BSB-3 – jQuery/Spine Shopping Cart Project&lt;/p&gt;
&lt;h3&gt;Models&lt;/h3&gt;
&lt;p&gt;In Spine, a model represents an entity, which has state (data) and logic to manipulate said data. A model can be saved, retrieved and even queried for (to an extent). Models can be stored in memory (the default) or use any of the storage modules provided such as Ajax or HTML5 Local Storage. Listing BSB-4 shows the basic Item model that represents an item in our shopping cart application.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;// Create the Item model.
var Item = Spine.Model.sub();
Item.configure("Item", "name", "pid", "price", "quantity");
&lt;/pre&gt;
&lt;p&gt;Listing BSB-4&lt;/p&gt;
&lt;p&gt;A Spine model “class” is created using the setup method of Spine.Model, which takes the name of the model and an array of properties. To make the model persist between page reloads we extend Item with the Spine.Model.Local module as shown in Listing BSB-5.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;// Persist model between page reloads.
Item.extend(Spine.Model.Local);
&lt;/pre&gt;
&lt;p&gt;Listing BSB-5&lt;/p&gt;
&lt;p&gt;The extend method adds class properties to the model. We now have an object that can be created, saved and retrieved from the browser local storage.&amp;#160;&lt;/p&gt;
&lt;p&gt;To add behavior to our model we use the include method which adds instance properties. Listing BSB-6 shows the four methods that we need for our Item model; increase, decrease, total and label.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;// Instance methods
Item.include({
    //
    total: function() {
        return (this.price * this.quantity);
    },
    //
    increase: function(quantity) {
        quantity = (typeof(quantity) != 'undefined') ? quantity : 1;
        this.quantity = this.quantity + quantity;
		this.trigger("quantityChanged");
    },
    //
    decrease: function(quantity) {
        quantity = (typeof(quantity) != 'undefined') ? quantity : 1;
        if (this.quantity &amp;gt;= quantity) {
            this.quantity = this.quantity - quantity;
        }
        else {
            this.quantity = 0;
        }
		this.trigger("quantityChanged");
    },
    // 
    label: function() {
        return (this.name + " - $" + this.price);
    }
    
});&lt;/pre&gt;
&lt;p&gt;Listing BSB-6&lt;/p&gt;
&lt;p&gt;To instantiate an Item we use the create method, which takes object literals for the parameters. A new model can be persisted using the save method. When a model is saved it is assigned an identifier that can be retrieved via the id property.  All three are demonstrated in Listing BSB-7.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;var item = new Item({name: "Product 1", pid: "0001" , price: 100.0, quantity: 1});
item.save();
alert("Just saved Item with id =&amp;gt; " + item.id);    
&lt;/pre&gt;
&lt;p&gt;Listing BSB-7&lt;/p&gt;
&lt;h3&gt;Controllers&lt;/h3&gt;
&lt;p&gt;Controllers in Spine are a combination of a traditional MVC controller and a view. Therefore controllers are in charge of rendering and manipulating one or more models in the context of the controller’s functionality.&lt;/p&gt;
&lt;p&gt;Our first Spine controller will deal with the rendering and manipulation of an individual Item. The CartItem controller will deal with user interface events to increase and decrease the quantity of an Item while keeping the user abreast of the changes. Listing BSB-8 shows the CartItem controller contained in the file cart_item.js.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;jQuery(function($){
    window.CartItem = Spine.Controller.sub({ 
        
        init: function(){
            var cartItem = this;
            
            this.item.bind("quantityChanged", function() { cartItem.updateQty() });
            
            $('#item_' + this.item.pid + ' .add').live('click', function(e) { 
                cartItem.add(); 
                e.preventDefault(); 
            });
            
            $('#item_' + this.item.pid + ' .remove').live('click', function(e) { 
                cartItem.remove(); 
                e.preventDefault(); 
            });
        },
        
        render: function(){
            this.el = $.mustache($("#cartItem").html(), this.item);
            
            return this;
        },
    
        // event handlers
        add: function(e) {
            this.item.increase();
        },
            
        remove: function(e) {
            this.item.decrease();
        },
    
        // ui methods
        updateQty: function() {
            $('#item_' + this.item.pid + ' #qty')
                .text(this.item.quantity)
                .effect("highlight", {}, 1500);
        }
    });
})
&lt;/pre&gt;
&lt;p&gt;Listing BSB-8&lt;/p&gt;
&lt;p&gt;Spine controllers are created using the create method of Spine.Controller, which takes an object literal that sets a wide variety of properties. In Listing BSB-8 we see the first property passed is named proxied and takes an array of Strings. The values are the name of the controller methods that need to be guaranteed to execute in the controller’s context (otherwise you’ll noticed that sometimes the this variable points to something other than the controller).&lt;/p&gt;
&lt;h3&gt;Events&lt;/h3&gt;
&lt;p&gt;In the controller’s init method we bind a custom event called "quantityChanged" of the enclosing Item model to the controller’s updateQty method.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;this.item.bind("quantityChanged", function() { cartItem.updateQty() }); 
&lt;/pre&gt;
&lt;p&gt;Listing BSB-9.1&lt;/p&gt;
&lt;p&gt;The model’s "quantityChanged" is&amp;#160;triggered in both the increase and decrease methods of the Item model:&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;this.trigger("quantityChanged");
&lt;/pre&gt;
&lt;p&gt;Listing BSB-9.2&lt;/p&gt;
&lt;p&gt;Also, in the init method, we wire the ‘add’ and ‘remove’ links of the CartItem to the add and remove methods which invoke the underlying Item model add and remove methods.&lt;/p&gt;
&lt;h3&gt;Rendering&lt;/h3&gt;
&lt;div&gt;To render the associated view for the CartItem controller we use the render method. In the render method we use jQuery to locate the element with id cartItem, which is a template, embedded in the HTML page as shown in Listing BSB-10.&lt;/div&gt;
&lt;pre class="brush: javascript;"&gt;render: function(){
            this.el = $.mustache($("#cartItem").html(), this.item);
            
            return this;
        }&lt;/pre&gt;
&lt;p&gt;Listing BSB-10&lt;/p&gt;
&lt;p&gt;The cartItem template is a Mustache.js Template that enables the creation of markup templates containing binding expressions. The mustache method clones the template contents and replaces the binding expressions ({{exp}}) with the values of the object passed, in our case in Listing BSB-11 the controller’s enclosed Item model.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;    
    &amp;lt;!-- Mustache :-{)~ Template for CartItem --&amp;gt;
    &amp;lt;script type="text/x-mustache-tmpl" id="cartItem"&amp;gt;
        &amp;lt;li class="product ui-state-default" id="item_{{pid}}" price="{{price}}"&amp;gt;
            {{label}}
            (&amp;lt;span id="qty"&amp;gt;{{quantity}}&amp;lt;/span&amp;gt;)
            &amp;lt;a href="#" class="add"&amp;gt;+&amp;lt;/a&amp;gt;
            &amp;lt;a href="#" class="remove"&amp;gt;-&amp;lt;/a&amp;gt;
        &amp;lt;/li&amp;gt;
    &amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Listing BSB-11&lt;/p&gt;
&lt;p&gt;To test our controller we need to instantiate an Item model and pass it to the controller. We can then render the controller on the DOM of an HTML page as shown in Listing BSB-12.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;    
	var item = new Item({name: "Product 1", pid: "0001" , price: 100.0, quantity: 1});
	var view = new CartItem({item: item});
	$("#item").html(view.render().el);
&lt;/pre&gt;
&lt;p&gt;Listing BSB-12&lt;/p&gt;
&lt;p&gt;A controller has an el (element) property that reflects the DOM element that will be the target of the rendering. The test page shown in Figure BSB-4 reveals that the CartItem controller accomplishes the functionality required to deal with a single Item model.&lt;/p&gt;
&lt;p&gt;&lt;img src="/system/images/BAhbBlsHOgZmSSIzMjAxMS8xMi8yNi8wOC8yMy8xNi85NTkvRmlndXJlX1NwaW5lX0JTQl80LnBuZwY6BkVU/Figure_Spine_BSB_4.png" title="Figure Spine Bsb 4" alt="Figure Spine Bsb 4" rel="225x255" height="289" width="446" /&gt;&lt;/p&gt;
&lt;p&gt;Figure BSB-4 – CartItem Controller in Action&lt;/p&gt;
&lt;h3&gt;Shopping Cart Controller&lt;/h3&gt;
&lt;p&gt;With the CartItem controller in place we can now concentrate on the ShoppingCart controller (shown in Listing BSB-13), which will manage a collection of Item models.&lt;/p&gt;
&lt;p&gt;Internally the ShoppingCart keeps the items dropped in the items property, which is initialized with an object literal in the init method. Also in the init method we set up the drop area for the drag-n-drop operation.&lt;/p&gt;
&lt;h3&gt;Persistence&lt;/h3&gt;
&lt;p&gt;In the init method we also query for any existing Item models that were previously saved by using the all method of the model (Item.all()). If any items are found then we simply add them to the cart using the addItem method.&lt;/p&gt;
&lt;h3&gt;Methods&lt;/h3&gt;
&lt;p&gt;The cart provides several aptly named methods to fulfill its functionality. The clear method iterates over all the contained Item models and invokes the destroy method which the cart listens to in order to animate the removal of rendered ItemCarts from the cart.&lt;/p&gt;
&lt;p&gt;The methods total, isEmpty and itemsCount return the total dollar amount for the cart, whether the cart is empty and the count of all unique items in the cart respectively.&lt;/p&gt;
&lt;p&gt;The drop method handles drop events similarly to the pure jQuery shopping cart implementation; it either creates a new item or increases the quantity of an existing item. The main difference being that the drop creates an Item model that is then rendered using the CartItem controller. Concerns separated!&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;    
jQuery(function($){
    window.ShoppingCart = Spine.Controller.sub({
        el: $("#theCart"),
        
        init: function() {
            var cart = this;
            this.items = {};
            $.each(Item.all(), function(){ cart.addItem(this); });
            this.el.droppable({ accept: '.product', drop: this.proxy(this.drop) });
            $('#dump', this.el).live('click', function() { cart.clear(); });
        },
        
        // removes all items from the cart
        clear: function() {
            $.each(this.items, function(){ this.destroy(); });
            this.items = {};
            this.updateCartTotal(); 
        },
        
        total: function() {
            var sum = 0.0;
            $.each(this.items, function(){ sum += this.total(); });

            return sum;
        },
        
        isEmpty: function() {
            return this.itemsCount() == 0;
        },
        
        itemsCount: function() {
            var size = 0;
            var items = this.items;
            $.each(items, function(){ if (items.hasOwnProperty(this)) size++; });

            return size;
        },
        
        drop: function(ev, ui) {
            var item_dropped = ui.draggable;
            var pid = item_dropped.attr('id');
            var price = item_dropped.attr('price');
            var name = item_dropped.attr('name');

            if (this.items.hasOwnProperty(pid)) {
                this.items[pid].increase();
            }
            else {
                var item = Item.create({name: name, pid: pid, price: price, quantity: 1});
                this.addItem(item);
                $(".items").append(CartItem.init({item: item}).render().el);
            }
        },
        
        render: function() {
            this.el.html($.mustache($("#shoppingCart").html(), {}));
            
            $('#dump').button();

            $.each(this.items, function(){ 
                $(".items").append(CartItem.init({item: this}).render().el);
            });
            
            this.updateCartTotal();
        },
        
        removeItem: function(item) {
            $('#item_' + item.pid).effect("puff", {}, "slow", function(){ $(this).remove(); });
        },
        
        updateCartTotal: function() {
            $('#total').text(this.total()).effect("highlight", {}, 1500);
        },
        
        removeIfQuantityZero: function(item) {
            if (item.quantity == 0) {
                this.removeItem(item);
                delete this.items[item.pid];
                item.destroy();
            }
        },
        
        addItem: function(item) {
            this.items[item.pid] = item;
            item.bind("quantityChanged", this.proxy(this.updateCartTotal));
            item.bind("quantityChanged", this.proxy(this.removeIfQuantityZero));
			item.bind("quantityChanged", function() { item.save() });
            item.bind("destroy", this.proxy(this.removeItem));
            item.save();
            this.updateCartTotal();
        }

    });
})
&lt;/pre&gt;
&lt;p&gt;Listing BSB-13&lt;/p&gt;
&lt;p&gt;At the end of Listing BSB-13 we can see that the addItem method sets several listeners to various events on the enclosed Item models. One of the advantages of frameworks like Spine is the ability to deal with standard changes in related models without having to tightly couple their implementation to the controllers. Also, note that in addItem we save the created models so that we can later retrieve them in case of a page refresh.&lt;/p&gt;
&lt;h3&gt;Tying It All Together&lt;/h3&gt;
&lt;p&gt;Finally, to kick everything in motion the application.js file begins by fetching any previously stored Item records, making the sample products draggable, creating a cart and rendering it.&lt;/p&gt;
&lt;pre class="brush: javascript;"&gt;  
jQuery(function($){
	Item.fetch();
	$(".product").draggable({ helper: 'clone', opacity: "0.5" });
	var cart = new ShoppingCart();
	cart.render();
});
&lt;/pre&gt;
&lt;p&gt;Listing BSB-14&lt;/p&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;In this article we’ve covered the basics of single page web applications. These applications are nothing new; we’ve attempted them in the past but now we have frameworks like jQuery to deal with browser disparities and Spine to inject the MVC sense of order.&lt;/p&gt;
&lt;p&gt;The new breed of MVC frameworks allows us to create clean, simple, componentized and event-oriented applications. We can separate our applications’ logic into cleanly defined areas of concern, cache data on the client side, minimize AJAX calls and provide many features that we would otherwise have to implement ourselves. We can now build rich state of the art JavaScript applications that can rival their desktop counterparts.&lt;/p&gt;
&lt;h3 class="fancy"&gt;References&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Spine:&amp;#160;&lt;a href="http://spinejs.com/" title="http://spinejs.com/"&gt;http://spinejs.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;jQuery: &lt;a href="http://http://jquery.com" title="http://http://jquery.com"&gt;http://jquery.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;jQuery UI: &lt;a href="http://jqueryui.com" title="http://jqueryui.com"&gt;http://jqueryui.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Mustache Templates Plugin:&amp;#160;&lt;a href="https://github.com/janl/mustache.js" title="https://github.com/janl/mustache.js"&gt;https://github.com/janl/mustache.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Example Code:&lt;/li&gt;
&lt;li&gt;	&lt;a href="https://github.com/bsbodden/jquery-shopping-cart" title="https://github.com/bsbodden/jquery-shopping-cart"&gt;https://github.com/bsbodden/jquery-shopping-cart&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;	&lt;a href="https://github.com/bsbodden/jquery-spine-shopping-cart" title="https://github.com/bsbodden/jquery-spine-shopping-cart"&gt;https://github.com/bsbodden/jquery-spine-shopping-cart&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="author-shortcodes"&gt;
			&lt;div class="author-inner"&gt;
				&lt;div class="author-image"&gt;
			&lt;img src="http://www.gravatar.com/avatar/270b71aa52e822fa5920e618fd693d0c.png?r=g&amp;amp;s=57&amp;amp;d=identicon" /&gt;
			&lt;div class="author-overlay"&gt;&lt;/div&gt;
		&lt;/div&gt;  
		&lt;div class="author-info"&gt;
			&lt;h1 style="font-size: 20px;"&gt;About The Author&lt;/h1&gt;
&lt;p&gt;Brian Sam-Bodden is avid developer, author and recognized international speaker that has spent over fifteen years working with object technologies.&amp;#160;&lt;/p&gt;
&lt;p&gt;He is the president and chief software architect for Integrallis, where he focuses on building great applications with Ruby, Rails, Groovy, Grails and Java. Brian is the creator of many Ruby open source utilities including the JRuby XML tool “Excemel”, the Component-Oriented Ruby Framework “Trellis” and numerous Ruby on Rails Plugins.&lt;/p&gt;
&lt;p&gt;He is also the author of Beginning POJOs: Spring, Hibernate, JBoss and Tapestry and has also co-authored the Apress Java title Enterprise Java Development on a Budget: Leveraging Java Open Source Technologies and contributed to O'reilly's 97 Things Every Project Manager Should Know.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://workingwithrails.com/recommendation/new/person/7570-brian-sam-bodden" title="Recommend Brian on Working With Rails"&gt;&lt;img src="http://workingwithrails.com/images/tools/compact-small-button.jpg" alt="Recommend Brian on Working With Rails" style="border-style: none" /&gt;&lt;/a&gt;
&lt;/p&gt;
		&lt;/div&gt; 
			&lt;/div&gt; 
		&lt;/div&gt;</description>
      <pubDate>Tue, 27 Dec 2011 18:00:00 CST</pubDate>
      <dc:creator>Brian Sam-Bodden</dc:creator>
    </item>
    <item>
      <title>Constant Pain with Non-Constant Constants</title>
      <link>http://projectautomationexperience.com/blog/ken_sipe/2011/12/constant_pain_with_non_constant_constants</link>
      <description>This thought has crossed my mind before... since it is on my mind now I thought I might share.  Perhaps it will help someone on their software development career path... or perhaps it is just me venting...&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Art of Coding&lt;/h2&gt;&lt;br /&gt;One of the greatest challenges of coding is being able to understand it.   Skill in coding is being able to understand the problem well enough to create a solution (otherwise known as coding).  &lt;em&gt;Great Skill&lt;/em&gt; is being able to write a solution so that someone else (including the future you) can read and understand what it is they are looking at.    This concept isn't new, but yet we seem to be either challenged with the concept... or distracted. Even back in 1952 (yes 1952!!), in the computer history archive a &lt;a href="http://archive.computerhistory.org/resources/text/Fortran/102653981.05.01.acc.pdf"&gt;set of lecture notes&lt;/a&gt; which in them states: "It is quite difficult to decipher coded programs even with notes and even if you yourself made the program several months ago."   It also states: "I think the answer is simple: to make it easy one must make coding comprehensible".   Well said!&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Point of Constants&lt;/h2&gt;&lt;br /&gt;One area that seems to be a constant :) struggle is constants.  There are at least a couple of justifications for using constants I can think of: 1) a point of reference for tools (autocomplete with intellisense in IDEs and refactoring), 2) A common holder of value for which if it changes will be realized across the system.    The main point of a constant isn't &lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself"&gt;DRY&lt;/a&gt; or reuse... a common point of confusion for some reason.&lt;br /&gt;&lt;br /&gt;IMO the stronger argument is point 2.  if you were coding in VI or emacs, point 1 may not be of value, but point 2 certainly would be.   If you name the reference of a constant the same name as the value of the constant... then you lose any the value of point 2. &lt;br /&gt;It must also be said that constants, although they add value, they make code less readable (see examples below).  If your constants have no value, they don't achieve points 1 and 2, then they need to be whacked!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Examples of Losing with Constants&lt;/h2&gt;&lt;br /&gt;This is real production code... some variables changed to obscure identify.&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;&lt;br /&gt;        // example 1   Really??  where does this end?&lt;br /&gt; String EMPTY_STRING = "";&lt;br /&gt;&lt;br /&gt;        // this isn't readable... it takes minutes (instead of seconds) to understand its value&lt;br /&gt;        // example 2&lt;br /&gt; String ADVERTISE_PROPERTY_PREFIX = OUR_PROPERTY_PREFIX + "advertise.";&lt;br /&gt; String ADVERTISE_TRADER_ADDRESS_PROPERTY = ADVERTISE_PROPERTY_PREFIX + "host";&lt;br /&gt; String ADVERTISE_CONTEXT_PROPERTY = ADVERTISE_PROPERTY_PREFIX + "context";&lt;br /&gt; String ADVERTISE_TYPE_PROPERTY = ADVERTISE_PROPERTY_PREFIX + "type";&lt;br /&gt;&lt;br /&gt;       // example 3&lt;br /&gt;       // here's a common one&lt;br /&gt;static final String TABLE_NAME = "email";&lt;br /&gt;&lt;br /&gt; // Column names for all the fields in the email table&lt;br /&gt;static final String ID = TABLE_NAME + ".email_id";&lt;br /&gt;static final String CUSTOMER_ID = TABLE_NAME + ".customer_id";&lt;br /&gt;static final String ADDRESS = TABLE_NAME + ".address";&lt;br /&gt;        // ...&lt;br /&gt;static final String FIELDS = ID + ", " + CUSTOMER_ID + ", " + ADDRESS + ", " + CREATED_BY + ", " + LAST_MOD_BY&lt;br /&gt;  + ", " + CREATE_DATE + ", " + LAST_MOD_DATE + ", " + TERM_DATE + ", " + WEB_USER_ID;&lt;br /&gt;&lt;br /&gt; // List of fields names with formatting used for select statements&lt;br /&gt;static final String SELECT_FIELDS = ID + ", " + CUSTOMER_ID + ", " + ADDRESS + ", " + CREATED_BY + ", "&lt;br /&gt;  + LAST_MOD_BY + ", " + "TO_CHAR(" + CREATE_DATE + ",'" + DATE_TIME_FORMAT + "')," + "TO_CHAR("&lt;br /&gt;  + LAST_MOD_DATE + ",'" + DATE_TIME_FORMAT + "')," + "TO_CHAR(" + TERM_DATE + ",'" + DATE_TIME_FORMAT&lt;br /&gt;  + "')," + WEB_USER_ID;&lt;br /&gt;&lt;br /&gt; // SQL used to create a new EMAIL record&lt;br /&gt;static final String CREATE_SQL = "INSERT INTO " + TABLE_NAME + " (" + FIELDS&lt;br /&gt;  + ") VALUES (?,?,?,?,?,SYSDATE,SYSDATE,NULL,?)";&lt;br /&gt;&lt;br /&gt; // SQL used to retrieve an email record by id&lt;br /&gt;static final String RETRIEVE_BY_ID_SQL = "SELECT " + SELECT_FIELDS + " FROM " + TABLE_NAME + " WHERE " + TERM_DATE&lt;br /&gt;  + " IS NULL AND " + ID + "=?";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For example 1... where does it end?  would you create a constant A = "A"?   When can EMPTY_STRING not be an empty string or ""?  In this case, we get no value and less readability.&lt;br /&gt;&lt;br /&gt;Example 2 is the chaining of constants, commonly found when there are a large number of property values being retrieved from a file or sys env.  While not as bad as example 1, it is less readable.   Having a prefix constant may be of value, but rarely is the chaining of constants of value.  It isn't worth trading the potential for a company name change or something similar for readability.    Or put another way, it isn't worth trading something that is unlikely to happen for something else which is more likely to be needed (that being the readability of the code)&lt;br /&gt;&lt;br /&gt;Example 3 I see all the time... argghhhhh... please... just stop!&lt;br /&gt;&lt;br /&gt;Examples of good constants would include, urls and database connections strings or a project defined standard date format.&lt;br /&gt;&lt;br /&gt;May your constants always be final!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7461275049781191261-4384339181115730031?l=kensipe.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
      <pubDate>Tue, 20 Dec 2011 14:55:01 CST</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-7461275049781191261.post-4384339181115730031</guid>
      <dc:creator>Ken Sipe</dc:creator>
    </item>
    <item>
      <title>Advanced Spock Techniques</title>
      <link>http://projectautomationexperience.com/blog/ken_sipe/2011/12/advanced_spock_techniques</link>
      <description>&lt;a href="http://cdn2-b.examiner.com/sites/default/files/c8/da/c8da7f602f266072aed0b46897be8610.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 110px; height: 82px;" src="http://cdn2-b.examiner.com/sites/default/files/c8/da/c8da7f602f266072aed0b46897be8610.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In recent years there have been a couple of tools that stand out when it comes to helping me be productive.   One of those is the groovy test framework &lt;a href="http://code.google.com/p/spock/"&gt;Spock&lt;/a&gt;.   It is worthy of an introductory blog post... but that isn't this post.   One of the challenges to Spock is the documentation isn't a complete as one would hope.  The &lt;a href="http://code.google.com/p/spock/wiki/GettingStarted"&gt;Spock Basics&lt;/a&gt; is fantastic when getting started but it is what it claims to be basics.     I've been speaking with &lt;a href="http://www.nofluffjuststuff.com/home/main"&gt;NFJS&lt;/a&gt; on the subject of Spock for the last half of 2011.  On 2 occasions I've had the look our red shirted friend in the picture has when asked about controlling aspects of mocks in spock... meaning I didn't have the answer.   In this case,  google didn't discover it either... a quick email to the &lt;a href="http://www.springone2gx.com/conference/speaker/peter_niederwieser"&gt;Peter Niederwieser&lt;/a&gt; reveals the previously undocumented solution. (at least that's my understanding)... and thanks Peter!  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Here we will discuss 2 advanced aspects of mocking with spock.  If you need more details on mocking in general hit the Spock site... or wait patiently for a future post:)&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3&gt;Problem Setup:&lt;/h3&gt;&lt;div&gt;When mocking with Groovy we get 2 benefits from the verification of the mock.  1) order of execution, 2) failure if another method on the mock was executed but was not setup in the demand configuration.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;void testDeposit() {&lt;br /&gt;&lt;br /&gt;        Account account = new Account(TEST_ACCOUNT_NO, 100)&lt;br /&gt;&lt;br /&gt;        def mock = new MockFor(AccountDao)&lt;br /&gt;        mock.demand.findAccount(TEST_ACCOUNT_NO) { account }&lt;br /&gt;        mock.demand.updateAccount(account) { assertEquals 150, account.balance  }&lt;br /&gt;&lt;br /&gt;        def dao = mock.proxyDelegateInstance()&lt;br /&gt;        def service = new AccountServiceImpl(dao)&lt;br /&gt;&lt;br /&gt;        service.deposit TEST_ACCOUNT_NO, 50&lt;br /&gt;        mock.verify dao&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Spock Cleanup&lt;/h3&gt;&lt;br /&gt;A similar solution in Spock might look like this:&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;    def "deposit into account test refactor"() {&lt;br /&gt;&lt;br /&gt;        def mock = Mock(AccountDao)&lt;br /&gt;        def service = new AccountServiceImpl(mock)&lt;br /&gt;&lt;br /&gt;        when:&lt;br /&gt;        service.deposit nmr, amt&lt;br /&gt;&lt;br /&gt;        then:&lt;br /&gt;        mock.findAccount(_) &gt;&gt; account&lt;br /&gt;        1 * mock.updateAccount(_)&lt;br /&gt;        0 * mock.createAccount(_)&lt;br /&gt;&lt;br /&gt;        and:&lt;br /&gt;        account.balance == total&lt;br /&gt;&lt;br /&gt;        where:&lt;br /&gt;        nmr   | account                 | amt | total&lt;br /&gt;        "101" | new Account("101", 100) | 50  | 150&lt;br /&gt;        "101" | new Account("101", 0)   | 50  | 50&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;However this solution doesn't guarantee order nor do we want to use the 0 * mock.&lt;method&gt; on all possible methods.  &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Spock Mock Solution&lt;/h3&gt;&lt;br /&gt;It turns out that we can repeatedly use the then: dsl to determine the order of events.  So we can modify the Spock code above with the following changes.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;        then:&lt;br /&gt;        1 * mock.findAccount("1234") &gt;&gt; account&lt;br /&gt;&lt;br /&gt;        then:&lt;br /&gt;        _ * mock.updateAccount(_)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In this case we are saying that the findAccount() method will be called exactly once and return the account object and "then" the updateAccount will be call any number of times with any type of argument.   The test will fail if the updateAccount is ever called prior to the findAccount being invoked first.&lt;br /&gt;&lt;br /&gt;We can use this same technique to solve the strictness concern we have as well by adding one more then: block of code as outlined below:&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;    then:&lt;br /&gt;        1 * mock.findAccount("1234") &gt;&gt; account&lt;br /&gt;&lt;br /&gt;        then:&lt;br /&gt;        _ * mock.updateAccount(_)&lt;br /&gt;&lt;br /&gt;        then:&lt;br /&gt;        0 * mock._&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In this case the last 0 * mock._ says to expect nothing else.  Ahhh.. the beauties of a dynamic language:)&lt;br /&gt;&lt;br /&gt;Happy Coding... may your builds never fail and your tests always green bar!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7461275049781191261-4078999687695672358?l=kensipe.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
      <pubDate>Wed, 14 Dec 2011 17:49:45 CST</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-7461275049781191261.post-4078999687695672358</guid>
      <dc:creator>Ken Sipe</dc:creator>
    </item>
    <item>
      <title>Git and GitHub Support in JetBrains YouTrack</title>
      <link>http://projectautomationexperience.com/blog/matthew_mccullough/2011/11/git_and_github_support_in_jetbrains_youtrack</link>
      <description>&lt;p&gt;I recently had the chance to get a demo of &lt;a href="http://jetbrains.com"&gt;JetBrains&lt;/a&gt; products&amp;#8217; &lt;a href="http://git-scm.com.com/"&gt;Git&lt;/a&gt; integration and to meet some of the JetBrains development team in person at &lt;a href="http://oredev.org/2011"&gt;Øredev&lt;/a&gt; in Malmö, Sweden.&lt;/p&gt;
&lt;p&gt;I love seeing things integrate better with the &lt;a href="http://developer.github.com/v3/"&gt;GitHub API&lt;/a&gt;. It really is fantastic to see what is possible when a rich Internet application additionally becomes a platform for apps that extend the core value proposition. &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; has executed on this quite well with their &lt;a href="http://developer.github.com/v3/"&gt;API, now at version 3.0&lt;/a&gt; and with features like gist, repo, user, and even organization management.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://ambientideas.com/blog/wp-content/uploads/2011/11/youtrack-issue-bug-tracker-jetbrains.jpg" alt="Youtrack issue bug tracker jetbrains" title="youtrack-issue-bug-tracker-jetbrains.jpg" border="0" width="483" height="89" style="float:right;" /&gt;I like to keep abreast of just about everything that happens in the Git world, and the JetBrains folks certainly as very active there. &lt;a href="http://www.jetbrains.com/youtrack/"&gt;The JetBrains issue tracking tool, YouTrack&lt;/a&gt;, makes extensive use of the GitHub API and has much in the way of Git love. I&amp;#8217;ve been pointing folks at the &lt;a href="http://tv.jetbrains.net/videocontent/youtrack-overview"&gt;YouTrack overview video&lt;/a&gt; if they want a quick summary and the &lt;a href="http://tv.jetbrains.net/videocontent/youtrack-github-integration"&gt;integration demo&lt;/a&gt;, if the GitHub facet is the attraction.&lt;/p&gt;
&lt;p&gt;It is always fun to ask a vendor for their view of what&amp;#8217;s important and what&amp;#8217;s next. The JetBrains team said (paraphrased):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Keyboard-centric approach: All common actions have handy shortcuts.&lt;/li&gt;
&lt;li&gt;Smart issue search: Search with queries similar to everyday language aided by completion and highlighting. For example, type &lt;code&gt;for me unresolved&lt;/code&gt; to filter down to open issues assigned to me.&lt;/li&gt;
&lt;li&gt;Batch modification commands similar to search queries: Select multiple issues and resolve them all by typing &lt;code&gt;fixed assignee Matthew&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Report from everywhere: You can report issues via email or any third party application via a REST API.&lt;/li&gt;
&lt;li&gt;Full customization: You can define and use new attributes for your bug tracking and &lt;a href="http://tv.jetbrains.net/videocontent/youtrack-customizable-workflow-overview"&gt;create workflows&lt;/a&gt; using a YouTrack workflow editor with a domain-specific language.&lt;/li&gt;
&lt;li&gt;Integration with VCSs via &lt;a href="http://www.jetbrains.com/teamcity/"&gt;TeamCity&lt;/a&gt; and native integration with &lt;a href="http://www.github.com"&gt;GitHub&lt;/a&gt;: You can specify an Issue ID and command to be applied to the issue right from commit comment. No opening the bug tracker just to change a bug state.&lt;/li&gt;
&lt;li&gt;REST API to perform any action programmatically: Complex actions like administration, issue tracking, and user management all have good treatment in the API which means tools can extend the tool if necessary.&lt;/li&gt;
&lt;li&gt;Import from other bug trackers: History can be imported from any issue tracker using the YouTrack Client Python library. There are even some ready to use scripts to import from the most popular trackers like JIRA, FogBugz, Mantis, and Bugzilla.&lt;/li&gt;
&lt;li&gt;Constant innovation with transparency: The &lt;a href="http://www.jetbrains.com/youtrack/roadmap/index.html"&gt;roadmap is public&lt;/a&gt; and &lt;a href="http://agilemanifesto.org/"&gt;agile&lt;/a&gt; project management is the next big focus.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;More Git-integrating tool reviews are being planned. Stay tuned.&lt;/p&gt;</description>
      <pubDate>Tue, 22 Nov 2011 22:54:00 CST</pubDate>
      <guid isPermaLink="true">http://ambientideas.com/blog/?p=317</guid>
      <dc:creator>Matthew McCullough</dc:creator>
    </item>
    <item>
      <title>MongoDB Grails and Copying Collections</title>
      <link>http://projectautomationexperience.com/blog/ken_sipe/2011/10/mongodb_grails_and_copying_collections</link>
      <description>I currently find myself working on a project where Grails and MongoDB are the technology stack... in fact that in part is some of the reason for being interested in the project.   I thought I would share 2 aspects of my learning so far:&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Grails + Mongo&lt;/h2&gt;&lt;br /&gt;We spent at least 2 weeks trying to understand which approach we were going to take for our persistent tier.   The general concensus was to use the Mongo GORM.   We started down that path and ran into a bug and then a limitation on embedding.  We got amazing support on the bug followed by the next release of the GORM option which fixed our initial document embedding concerns.   We ran into more problems.&lt;br /&gt;&lt;br /&gt;We switched to the morphia driver... once again... challenges caused lots of frustration.   The challenges included getting other plugins to work with this driver, the fact that the morphia "domain" objects couldn't be in the standard grails domain folder, which further complicated mocking.  Frustrations with getting full capabilities of getting spring security to work.   It turns out that with spring security there are a number of relational assumptions (along with assumptions of objects being domain classes.. meaning they live in the grails domain package space) which cause problems when you are using NoSQL.&lt;br /&gt;&lt;br /&gt;The morphia had another limitation we couldn't live with... we wanted the ability to have different types of objects mapped to the same collection.  It appears to me that the Mongo efforts in the Grails space are bolt ons to a rational model.  You can get it to work when thinking with a RDBMS mindset.  They seem to break down with a NoSQL mindset... this certainly could be attributed to user error (meaning me).   I believe we gave it a good try... however the project is under the gun and we didn't have time to "play" with it or wait for responses.&lt;br /&gt;&lt;br /&gt;Alas we created our own solution...  one of our significant constraints was to be prepared for extremely large scale.  This had us duplicating a lot of documents not common in RDBMS solutions... along with the fact we needed to control the number of queries.   Ideally we want 1 query for a page... certainly for the main page which is high laden with dynamic content.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Mongo Copying Documents - Collection to Collection&lt;/h2&gt;&lt;br /&gt;I'm really getting to like Mongo... a lot.  One of the downsides is there is limited documentation... including limited forum comments on it.   Because of this, I've decided to post interesting solutions to problems as I discover them... time permitting.  so for todays tip.   I recently needed to duplicate a "record" in mongo speak a document in a collection.   There is so much information out there on how not to duplicate records that a google search at this point usually points you in the wrong direction.  My situation was such that we have a CMS component to our application, which sets a publish day on content.   What I needed was the ability to duplicate a record (so the BSON id would need to change and set a new publish day.&lt;br /&gt;&lt;br /&gt;The first thing to recognize for those new to Mongo is that the Mongo console (the command line client to Mongo) works with javascript... so get your javascript fu ready... no.. not your jQuery fu... your plain jane generic javascript fu:)&lt;br /&gt;&lt;br /&gt;Here is the solution I came up with:&lt;br /&gt;&lt;pre class="brush: javascript"&gt;&lt;br /&gt;db.NewsItem.find({newsType: "Blah"}).forEach( function(x){ x._id = new ObjectId(); x.publishDay=283;  db.NewsItem.insert(x)} );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So it turns out that you can pass a lambda expression to the forEach method of the collection.   The trick is to assign a new ObjectId() to the _id, make any other assignments and then insert into your collection of choice... in this case back into the same collection.   This comes in handy as well when you want to backup a collection real quick. (yea, I know you could use the mongodump and mongorestore, for a quick temp solution this just seems more convenient)&lt;br /&gt;&lt;pre class="brush: javascript"&gt;&lt;br /&gt;db.NewsItem.find({publishDay : 285}).forEach( function(x){ db.NewsItemBackup.insert(x)} );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Happy Coding!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7461275049781191261-8967771380973474090?l=kensipe.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 13 Oct 2011 09:29:42 CDT</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-7461275049781191261.post-8967771380973474090</guid>
      <dc:creator>Ken Sipe</dc:creator>
    </item>
    <item>
      <title>JavaOne: Rocking the Gradle</title>
      <link>http://projectautomationexperience.com/blog/ken_sipe/2011/10/javaone_rocking_the_gradle</link>
      <description>Presenting Rocking the Gradle at &lt;a href="http://www.oracle.com/javaone/index.html"&gt;JavaOne&lt;/a&gt; tomorrow 12:30pm at the Parc 55... see you there!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7461275049781191261-4379207445284679082?l=kensipe.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
      <pubDate>Wed, 05 Oct 2011 11:06:16 CDT</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-7461275049781191261.post-4379207445284679082</guid>
      <dc:creator>Ken Sipe</dc:creator>
    </item>
    <item>
      <title>Git at the NHJUG</title>
      <link>http://projectautomationexperience.com/blog/matthew_mccullough/2011/07/git_at_the_nhjug</link>
      <description>&lt;h2&gt;NHJUG&lt;/h2&gt;
&lt;p&gt;I had the wonderful opportunity of being sponsored by &lt;a href="http://nofluffjuststuff.com"&gt;No Fluff, Just Stuff Symposiums&lt;/a&gt; to speak at the &lt;a href="http://www.nejug.org/events/show/129"&gt;New Hampshire JUG&lt;/a&gt; in Portsmouth on Tuesday. It was a lively crowd of 20 or so persons hosted by the excellent &lt;a href="http://twitter.com/TheSleepyVegan"&gt;Ted Pennings&lt;/a&gt;, &lt;a href="http://pblog.theothermattm.com/"&gt;Matt Merrill&lt;/a&gt;, &lt;a href="http://twitter.com/nh_jug"&gt;NHJUG&lt;/a&gt;, and &lt;a href="http://twitter.com/curryscott"&gt;Scott Curry&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://ambientideas.com/blog/wp-content/uploads/2011/07/portsmouth-nejug1.jpg" alt="Portsmouth nejug" title="portsmouth-nejug.JPG" border="0" width="600" height="448" /&gt;&lt;/p&gt;
&lt;p&gt;We discussed Git, GitHub, IntelliJ, and eGit with regards to their importance to the broad JVM ecosystem. Many insightful questions were asked, such as &amp;#8220;is the efficiency of the hard links to unchanged blobs maintained on Windows.&amp;#8221; The answer was yes, because this is not actually a POSIX &lt;em&gt;hardlink&lt;/em&gt; for commits, but rather an implementation &lt;strong&gt;like, but not exactly hardlinks&lt;/strong&gt; inside Git &lt;em&gt;tree&lt;/em&gt; objects.&lt;br /&gt;
&lt;h2&gt;CFMeetup&lt;/h2&gt;
&lt;p&gt;On Thursday, I had the equally delightful opportunity to speak to the &lt;a href="http://www.meetup.com/coldfusionmeetup/"&gt;CFMeetup online group&lt;/a&gt;, hosted by &lt;a href="http://twitter.com/carehart"&gt;Charlie Aerhart&lt;/a&gt; and facilitated in part by &lt;a href="http://twitter.com/mikehenke"&gt;Mike Henke&lt;/a&gt;, and supported by &lt;a href="http://twitter.com/TimCunningham71"&gt;Tim Cunningham&lt;/a&gt;.  &lt;a href="http://twitter.com/cfmeetup"&gt;It&lt;/a&gt; had a turnout of 35-45 persons, and has a significant additional viewership for the &lt;a href="http://ow.ly/5KtdS"&gt;recorded sessions at Vimeo&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Resources&lt;/h2&gt;
&lt;p&gt;I promised some links to Git resources and they are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.ambientideas.com/presentation/Git_Going_with_DVCS_%20v1.6.3-CL.pdf"&gt;Presentation slides in PDF format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bit.ly/gitlinks"&gt;Curated Git links&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://delicious.com/matthew.mccullough/git+gui"&gt;Git GUIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://progit.org"&gt;ProGit.org Free Online Book&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gitorious.org"&gt;Gitorious open source web app for self-hosted Git repos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com"&gt;GitHub&amp;#8217;s unlimited free open source project hosting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Sat, 23 Jul 2011 22:29:00 CDT</pubDate>
      <guid isPermaLink="true">http://ambientideas.com/blog/?p=314</guid>
      <dc:creator>Matthew McCullough</dc:creator>
    </item>
    <item>
      <title>Have a Relationship with your Customers</title>
      <link>http://projectautomationexperience.com/blog/david_bock/2011/06/have_a_relationship_with_your_customers</link>
      <description>&lt;p&gt;I have been a customer of Tivo for a long time; I first saw one at a friend&amp;#39;s house in the fall of 1999, and bought one for myself that Christmas.&amp;#0160; Over the years I have owned somewhere around 6 tivos... Upgrading when the series2, series3, and most recently the Tivo Premiere came out.&lt;br /&gt;&lt;br /&gt;Of course at its heart, the Tivo is a computer with a hard drive, and in the past 12 years I&amp;#39;ve had a few technical issues.&amp;#0160; This story starts last month when my Tivo Premiere died a horrible hard drive death and needed to be replaced, and ends with a lesson on the importance of having a relationship with your customers.&lt;br /&gt;&lt;br /&gt;I wasn&amp;#39;t looking forward to replacing the Tivo - besides the call to Comcast (which is an entirely separate blog post), I know from experience that every Tivo is a blank slate...&amp;#0160; I have to &amp;#39;teach&amp;#39; it everything about me again... the shows I record, the stuff it should suggest for me, and so on.&lt;br /&gt;&lt;br /&gt;Once I got the box set up, I was greeted with a &amp;quot;Welcome to Tivo&amp;quot; message in the Tivo&amp;#39;s &amp;quot;messages and settings&amp;quot; that politely told me what I needed to know to use my Tivo, as if I was a first-time user.&amp;#0160; I was slightly annoyed at this...&amp;#0160; I thought to myself &amp;quot;Tivo *knows* who I am - this Tivo is linked to a lifetime account.&amp;#0160; Why not have a welcome message that says &amp;#39;Here&amp;#39;s your replacement Tivo - we hope Rudy at the service center was able to resolve your issue.&amp;#39;?&lt;br /&gt;&lt;br /&gt;Of course, Tivo could easily do a lot better than that suggestion.&amp;#0160; My Tivo is linked to an account where I can schedule shows on the Tivo website; Why not back up my preferences there, and automatically download them to the new tivo?&amp;#0160; Why do I have to set up, yet again, things like &amp;quot;Record episodes of Phineas and Ferb off of DisneyHD&amp;quot;?&amp;#0160; I&amp;#39;m not asking Tivo to back up tons of data - not the actual shows, just the &amp;#39;metadata&amp;#39; about my shows, my thumbs up and down ratings, the premium channels I subscribe to, etc.&amp;#0160; This can&amp;#39;t be more than a few hundred kilobytes. (I would think they would be interested in that data too - wouldn&amp;#39;t TV executives PAY to know how many people gave a TV show a thumbs up vs. a thumbs down rating?).&lt;br /&gt;&lt;br /&gt;A week after I set up my replacement Tivo, I received a new message that says &amp;quot;You may have noticed extra recordings that you didn&amp;#39;t request - these are Tivo Suggestions&amp;quot;.&amp;#0160; This reminded me how annoyed I was...&amp;#0160; &amp;quot;Yes, I know you suggest shows to me - you&amp;#39;ve been doing it for ELEVEN YEARS...&amp;#0160; DON&amp;#39;T YOU KNOW WHO I AM?!?&amp;quot;&amp;#0160; I began to get the feeling that Tivo, as a company, doesn&amp;#39;t care that I&amp;#39;m a loyal customer.&amp;#0160; They should be sending me a message that says &amp;quot;Its been a week and we see you&amp;#39;re recording your preferred shows again.&amp;#0160; We&amp;#39;re happy everything was set up properly with your cable company&amp;quot;.&lt;br /&gt;&lt;br /&gt;Another week went by and I got another message &amp;quot;Have you ever missed an episode of your favorite program?&amp;#0160; Learn how to set up a Season Pass&amp;quot;.&amp;#0160; Sigh.&amp;#0160; Perhaps you didn&amp;#39;t notice, but I&amp;#39;ve already set up, like, 70 of them?&amp;#0160; Remember me?&amp;#0160; I was mildly annoyed at having to set everything up - but weeks later, Tivo&amp;#39;s naive attempts at customer contact are simply reinforcing the negativity of the whole experience.&lt;br /&gt;&lt;br /&gt;Now, I&amp;#39;m not expecting Tivo to greet me by name when I call their service department, or send me cookies at Christmas time, but they can do a lot better than this. As a software engineer, I know the things I&amp;#39;m suggesting are next to trivial to implement.&amp;#0160; I&amp;#39;m also quite sure the Tivo engineers have a list of user stories like these sitting in an idea tracker somewhere...&amp;#0160; The only reason Tivo, as a company, would not do these things is because they haven&amp;#39;t been made a priority.&lt;br /&gt;&lt;br /&gt;Thats right, Tivo, as a company, has not made it a priority to have a relationship with their customers.&lt;br /&gt;&lt;br /&gt;As much as I love my Tivo, I think they survive because their biggest competition is from cable-proprietary DVRs... and we all know the track record of customer relationship management cable companies typically have.&amp;#0160; Tivo should be thankful Apple didn&amp;#39;t make the AppleTV a DVR... I don&amp;#39;t think they could survive the competition.&amp;#0160; If Apple made a DVR, I&amp;#39;m sure it would be sending me tweets: &amp;quot;Hey Dave - Neal DeGrasse Tyson is going to be on Letterman tonight - don&amp;#39;t worry, I&amp;#39;ll record it for you.&amp;quot;&lt;br /&gt;&lt;br /&gt;You know what would have been the ultimate experience?&amp;#0160; A message on my tivo 2 months ago that said &amp;quot;We&amp;#39;ve noticed your Tivo is beginning to have issues with its hard drive.&amp;#0160; We&amp;#39;ve backed your schedule data up and scheduled a hardware replacement under warranty.&amp;#0160; call 1-800-get-tivo to schedule your return and replacement&amp;quot;.&amp;#0160; Upon plugging my new Tivo in, a message like &amp;quot;We&amp;#39;ve downloaded and rescheduled your shows and noticed you&amp;#39;ve inserted your cable card.&amp;#0160; You now need to call 1-800-comcast, and give them this MAC ID and Card Pairing Code to have them reactivate your cable service&amp;quot;.&amp;#0160; Every piece of hardware and data is available to make that possible; all thats missing is software.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Is there a lesson here?&amp;#0160; Yes!&amp;#0160; We can trivially use the data we have on our customers to improve their experience, and make it seem like they have a more personal relationship with a big faceless company.&amp;#0160; How can you improve your relationship with your customers?&lt;/p&gt;</description>
      <pubDate>Thu, 30 Jun 2011 08:56:00 CDT</pubDate>
      <guid isPermaLink="true">http://blog.codesherpas.com/on_the_path/2011/06/have-a-relationship-with-your-customers.html</guid>
      <dc:creator>David Bock</dc:creator>
    </item>
    <item>
      <title>Unified (as much as possible) Logging Using SLF4J</title>
      <link>http://projectautomationexperience.com/blog/baruch_sadogursky/2011/06/unified_as_much_as_possible_logging_using_slf4j</link>
      <description>&lt;p&gt;Integrating, integrating, integrating. That&amp;#8217;s what we do in Java enterprise development. Persisting objects with Hibernate wrapped by JPA using C3Po (or JTA?) (or MongoDB over Morphia?), processed with JBMP, created by JAXB (jackson-json?) from JAX-RS scheduled by Quartz &amp;#8230; (a few dozen frameworks later) &amp;#8230; all this glued with Spring (or Guice?) deployed on Jetty (or Tomcat, JBoss, Resin?) into cluster by Terracotta (or Hadoop, GigaSpaces, JBoss cache, Infinispam?). Ah, and all this built using &lt;span style="text-decoration:line-through;"&gt;Maven&lt;/span&gt; Gradle with Artifactory on Jenkins. I sure forgot ½ of the frameworks we constantly use.&lt;/p&gt;
&lt;p&gt;Generally we don&amp;#8217;t mind much about the internals of the frameworks we use (as long as they are good) &amp;#8211; the whole encapsulation stuff is the last &lt;a href="http://tech.puredanger.com/2010/02/25/questioning-oo/" target="_blank"&gt;undoubted&lt;/a&gt; good thing. But except for the API (part of which is the configuration) frameworks have another user-facing end – the logging. When we build a &lt;strong&gt;system&lt;/strong&gt; we want it to behave as one system – single configuration from one end, and single log from another (break it to different files, if you wish, but it should still be a unified logging system).&lt;/p&gt;
&lt;p&gt;The reality is that there is no standard de-facto for logging. The standard de-jure &amp;#8211; &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/logging/" target="_blank"&gt;JUL&lt;/a&gt;, is not very popular because of its lack of functionality (compared to alternatives) and its suboptimal performance. And then there is &lt;a href="http://logging.apache.org/log4j/" target="_blank"&gt;Log4J&lt;/a&gt;, which almost became standard, but did not. And there is &lt;a href="http://logback.qos.ch/" target="_blank"&gt;logback&lt;/a&gt;, which is a Log4J &lt;a href="http://logback.qos.ch/reasonsToSwitch.html"&gt;trashover&lt;/a&gt;, and there are facades (&lt;a href="http://commons.apache.org/logging/" target="_blank"&gt;JCL&lt;/a&gt; and &lt;a href="http://www.slf4j.org/" target="_blank"&gt;SLF4J&lt;/a&gt;), which try to unite all this zoo, and some others, which you have probably never heard of, like &lt;a href="http://www.syslog4j.org/" target="_blank"&gt;syslog4j&lt;/a&gt;*, &lt;a href="http://www.theobjectguy.com/javalog/" target="_blank"&gt;logging framework by the Object Guy&lt;/a&gt;, &lt;a href="http://java-source.net/open-source/logging" target="_blank"&gt;jLo, MonoLog, Lumberjack, Houston, JTraceDump, qflog, LN2, TracingClassLoader, SMTPHandler, Log4Ant, Simple Log, Log Bridge, Craftsman Spy, Pencil, JDLabAgent, Trace Log, JDBC Logger, LimpidLog and Microlog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let it be, you’d say – why not have many logging tools, which are good and diverse! Well, the problem, as I’ve already mentioned, is that they leak out of the frameworks. Their diverse configuration leaks from one end, while their diverse output from another. Spring uses Log4J over JCL. So does Hibernate. Jetty uses Logback over SLF4J. Some (like Terracotta modules) use plain Log4J, Jersey uses JUL.  This means we end up with 5 separate configurations (Log4J, SLF4J, Logback, JCL and JUL) and 3 different types of log files (Log4j, Logback and JUL). What a system!&lt;/p&gt;
&lt;p&gt;To make the long story short &amp;#8211; How can we achieve the desired consolidation? Clearly, we need a facade. There are two most commonly used &amp;#8211; SLF4J and JCL. JCL is known for its &lt;a href="http://articles.qos.ch/classloader.html" target="_blank"&gt;classloader hell&lt;/a&gt;, SLF4J is newer, better performing, smarter, simplier to use and generally provides better quality for the same buck (well, no buck &amp;#8211; both are open source, of course), so we&amp;#8217;ll stick to it. SLF4J is an adapter &amp;#8211; thin layer of API to and from different logging implementations. Yap, both ways. It means with SLF4J we can use JUL API on top and log using Log4J in the bottom!&lt;/p&gt;
&lt;p&gt;First we need to pick an actual logger. Log4j was considered the best choice up until recently (2006) when Ceki Gülcü decided he needed a fresh start and rewrote from scratch a new Java logging framework, just&lt;a href="http://xhab.blogspot.com/2007/03/new-logging-experience.html" target="_blank"&gt; better than log4j&lt;/a&gt;, called Logback. We can give it a try as our underlying logging implementation (we can switch in a moment, as we are using  good facade, remember?).&lt;/p&gt;
&lt;p&gt;So, here&amp;#8217;s what we have to do:&lt;/p&gt;
&lt;ol&gt;
&lt;ol&gt;
&lt;li&gt;Establish our own good logging:
&lt;ol&gt;
&lt;ol&gt;
&lt;li&gt;Add Logback to our classpath&lt;/li&gt;
&lt;li&gt;Add SLF4J API to our classpath&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;p&gt;Done here. Now our own brand new code will use top-notch logging.&lt;/li&gt;
&lt;li&gt;Now for the tricky part. Let&amp;#8217;s make the example stack I listed above taking configuration from one source (our config files) and writing to one target (files, listed in our configuration)&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;All the tools using SLF4J will just work. That includes dozen of Apache projects, inc. Camel and Mina, some SpringSource projects and &lt;a href="http://www.slf4j.org/" target="_blank"&gt;many others&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Now let&amp;#8217;s start rolling with all the rest. This is how you do it (click to enlarge):&lt;br /&gt;
&lt;a href="http://www.slf4j.org/images/bridging.png"&gt;&lt;img class="alignnone" title="Bridging architecture" src="http://www.slf4j.org/images/bridging.png" alt="Bridging architecture" width="297" height="162" /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;Jakarta Commons Logging:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;Remove commons-logging.jar from your classpath. Usually, it is transitive dependency from the framework, so you need to instruct your build tool on how to do it. What a lucky coincidence, I just wrote &lt;span style="text-decoration:line-through;"&gt;short&lt;/span&gt; and instructive &lt;a title="Banning Transitive Dependencies With Maven2/3, Gradle and Ivy" href="http://jbaruch.wordpress.com/2011/06/22/banning-transitive-dependencies-with-maven23-gradle-and-ivy/"&gt;blog post&lt;/a&gt; about how to do it!&lt;/li&gt;
&lt;li&gt;Add jcl-over-slf4j.jar instead. It contains alternative commons-logging API implementation, so the code will run just fine.&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;Log4J:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;Same goes here! Remove log4j.jar from your classpath (Again, it would usually be a transitive dependency from the framework, look &lt;a title="Banning Transitive Dependencies With Maven2/3, Gradle and Ivy" href="http://jbaruch.wordpress.com/2011/06/22/banning-transitive-dependencies-with-maven23-gradle-and-ivy/"&gt;here&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Add log4j-over-slf4j.jar instead. It contains alternative log4j API implementation, so the code will run just fine.&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;JUL:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;Well, you can&amp;#8217;t remove JUL from classpath (it&amp;#8217;s a part of the JRE, dude). For the same reason SLF4J can&amp;#8217;t reimplement JUL&amp;#8217;s API.&lt;/li&gt;
&lt;li&gt;Add jul-to-slf4j.jar. It will translate java.util.logging.LogRecord objects into their SLF4J equivalent.&lt;/li&gt;
&lt;li&gt;Install &lt;a href="http://www.slf4j.org/api/org/slf4j/bridge/SLF4JBridgeHandler.html"&gt;SLF4JBridgeHandler&lt;/a&gt; and &lt;a href="http://logback.qos.ch/manual/configuration.html#LevelChangePropagator"&gt;LevelChangePropagator&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Expect 20% decrease in performance (so use it wisely).&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;All done&lt;/strong&gt;. Now both our code and all the 3rd paries configured from single source and write to single target. Hooray!&lt;/p&gt;
&lt;p&gt;&lt;small&gt;* syslog4j claims it is cross-platform. Well,  I&amp;#8217;ll just quote: &amp;#8220;&lt;strong&gt;Is Syslog4j cross-platform?&lt;/strong&gt; Yes! Syslog4j UDP/IP and TCP/IP clients should work in any typical Java JRE environment.&amp;#8221;&lt;/small&gt;&lt;/p&gt;
&lt;br /&gt;Filed under: &lt;a href='http://blog.sadogursky.com/category/frameworks/'&gt;Frameworks&lt;/a&gt; Tagged: &lt;a href='http://blog.sadogursky.com/tag/jcl/'&gt;jcl&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/jul/'&gt;jul&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/log/'&gt;log&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/log4j/'&gt;log4j&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/logback/'&gt;logback&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/slf4j/'&gt;slf4j&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jbaruch.wordpress.com/34/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jbaruch.wordpress.com/34/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jbaruch.wordpress.com/34/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jbaruch.wordpress.com/34/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jbaruch.wordpress.com/34/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jbaruch.wordpress.com/34/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jbaruch.wordpress.com/34/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jbaruch.wordpress.com/34/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jbaruch.wordpress.com/34/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jbaruch.wordpress.com/34/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jbaruch.wordpress.com/34/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jbaruch.wordpress.com/34/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jbaruch.wordpress.com/34/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jbaruch.wordpress.com/34/" /&gt;&lt;/a&gt; &lt;img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.sadogursky.com&amp;#038;blog=481424&amp;#038;post=34&amp;#038;subd=jbaruch&amp;#038;ref=&amp;#038;feed=1" width="1" height="1" /&gt;</description>
      <pubDate>Wed, 22 Jun 2011 01:40:00 CDT</pubDate>
      <guid isPermaLink="true">http://jbaruch.wordpress.com/?p=34</guid>
      <dc:creator>Baruch Sadogursky</dc:creator>
    </item>
    <item>
      <title>Banning Transitive Dependencies With Maven2/3, Gradle and Ivy</title>
      <link>http://projectautomationexperience.com/blog/baruch_sadogursky/2011/06/banning_transitive_dependencies_with_maven2_3_gradle_and_ivy</link>
      <description>&lt;p&gt;Oh, you are using build tool with dependency management? Good! Be it Maven2/3, Gradle or Ivy, your life as devops or developer is much easier. Until you hit it. The evil transitive dependency. How can it be evil you ask? When the classes in it clash with the classes you really need.  Here&amp;#8217;s some use-cases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Same dependency, different jar names, two examples here:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;The Jakarta Commons renaming effort: &lt;a href="http://repo1.maven.org/maven2/commons-io/commons-io/1.3.2/"&gt;commons-io:commons-io:1.3.2&lt;/a&gt; and &lt;a href="http://repo1.maven.org/maven2/org/apache/commons/commons-io/1.3.2/"&gt;org.apache.commons:common-io:1.3.2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Spring Framework artifacts naming convention alternatives: &lt;a href="http://repo1.maven.org/maven2/org/springframework/"&gt;spring-beans, spring-context, etc&lt;/a&gt; in repo1 versus &lt;a href="http://ebr.springsource.com/repository/app/bundle/detail?name=org.springframework.beans"&gt;org.springframework.beans, org.springframework.context, etc&lt;/a&gt;in
&lt;div id="site-name"&gt;SpringSource EBR.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;Different packaging of the sample classes, many examples here:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;OSGi repackagings:&lt;a href="http://repo1.maven.org/maven2/asm/asm/3.2/"&gt; asm:asm:3.2&lt;/a&gt; and &lt;a href="http://ebr.springsource.com/repository/app/bundle/version/detail?name=com.springsource.org.objectweb.asm&amp;amp;version=3.2.0"&gt;org.objectweb.asm:com.springsource.org.objectweb.asm:3.2.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Modularization of Spring 2.5.6: &lt;a href="http://repo1.maven.org/maven2/org/springframework/spring/2.5.6/"&gt;as single jar&lt;/a&gt; and as &lt;a href="http://repo1.maven.org/maven2/org/springframework/"&gt;spring-whatever multiple modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Xerces and Xalan are included in JDK since 1.5. They are still present as transitive dependencies in all the tools which support JDK 1.4.&lt;/li&gt;
&lt;li&gt;Alternative packagings with and without dependencies: &lt;a href="http://repo1.maven.org/maven2/cglib/cglib/"&gt;cglib:cgli&lt;/a&gt;b and &lt;a href="http://repo1.maven.org/maven2/cglib/cglib-nodep/"&gt;cglib:cglib-nodep&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Project merges like &lt;a href="http://repo1.maven.org/maven2/com/google/collections/google-collections/"&gt;Google collections&lt;/a&gt;, which are now included in &lt;a href="http://repo1.maven.org/maven2/com/google/guava/guava/"&gt;Google Guava&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;Deliberately reimplemented interfaces, for example for &lt;a title="Unified (as much as possible) logging using SLF4J" href="http://jbaruch.wordpress.com/2011/06/22/unified-logging-using-slf4j/"&gt;bridging legacy APIs to new implementation, such as in SLF4J&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Your patches for 3rd-party tools.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All those may end up with 2 or more classes with the same name in the classpath. Why it is bad? Java class identifier consists of fully-qualified class name and the classloader that loaded it, so if two classes with the same name reside in same classpath JVM considers them to be the same class, and only one of them will be loaded. Which one? The first classloader encounters. Which one will it be? You have no idea.&lt;br /&gt;
When the duplicated classes are exactly the same, you will never notice. But if the classes are different, you&amp;#8217;ll start getting runtime exceptions, such as NoSuchMethodError, NoClassDefFoundError and friends. That&amp;#8217;s because other classes expect for find one API, but encounter another one &amp;#8211; wrong class was loaded first. Not fun.&lt;/p&gt;
&lt;p&gt;Now, when you know how evil they are, let&amp;#8217;s take those bastards down!&lt;/p&gt;
&lt;h4&gt;Maven 2/3&lt;/h4&gt;
&lt;p&gt;There is no simple way (Maven&amp;#8217;s tagline) to exclude some dependency from all the scopes. I&amp;#8217;ll show two cases &amp;#8211; manual exclusion and working with IntelliJ IDEA:&lt;/p&gt;
&lt;ol&gt;
&lt;ol&gt;
&lt;li&gt;Stage 1: exclude all the banned dependencies one by one:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;Manually edit Maven&amp;#8217;s poms&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;For each evil dependency:&lt;/li&gt;
&lt;li&gt;Find which top-level dependency brings the evil transitive hitcher with it. This is done by using Maven Dependency Plugin:
&lt;pre&gt;mvn dependency:tree -Dincludes=commons-logging:commons-logging&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;You&amp;#8217;ll get something like this:
&lt;pre&gt;[INFO] com.mycompany.myproduct:rest-client:1.0
[INFO] \- org.springframework:spring-webmvc:jar:3.0.5.RELEASE:compile
[INFO]    \- org.springframework:spring-core:jar:3.0.5.RELEASE:compile
[INFO]       \- commons-logging:commons-logging:jar:1.1.1:compile&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Go to the pom.xml with your dependency management (you use dependency management, don&amp;#8217;t you? If you don&amp;#8217;t, don&amp;#8217;t tell anyone, &lt;a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management"&gt;go and start using it&lt;/a&gt;) find spring-webmvc dependency and add an exclusion to it:
&lt;pre&gt;&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;1 &lt;/span&gt;    &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;2 &lt;/span&gt;    	&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;org.&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;springframework&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;3 &lt;/span&gt;    	&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;spring-&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;webmvc&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;4 &lt;/span&gt;    	&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;3.0.5.RELEASE&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;5 &lt;/span&gt;        &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;exclusions&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;6 &lt;/span&gt;            &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;exclusion&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;7 &lt;/span&gt;                &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;commons-logging&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;8 &lt;/span&gt;                &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;commons-logging&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;9 &lt;/span&gt;            &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;exclusion&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;10 &lt;/span&gt;        &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;exclusions&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;11 &lt;/span&gt;    &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;dependency&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;Working with IntelliJ IDEA:&lt;br /&gt;
&lt;a href="http://jbaruch.files.wordpress.com/2011/06/2011-06-21_131016.png"&gt;&lt;img class="alignnone size-thumbnail wp-image-129" title="IntelliJ IDEA Maven Dependencies" src="http://jbaruch.files.wordpress.com/2011/06/2011-06-21_131016.png?w=145&amp;h=150" alt="IntelliJ IDEA Maven Dependencies" width="145" height="150" /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;ol&gt;
&lt;ol&gt;
&lt;li&gt;Open Maven Dependencies Graph.&lt;/li&gt;
&lt;li&gt;Filter it by the dependency you are looking for.&lt;/li&gt;
&lt;li&gt;Select it and press Shift-Delete.&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;li&gt;Good job! Your nailed them down in the current version of your build. But what happens when someone adds a new 3rd party dependency and brings some bad stuff with it as transitives? You need to protect your build from this scenario. So, stage 2: Fail the build if one of the banned dependencies ever added to the build with &lt;a href="http://maven.apache.org/enforcer/enforcer-rules/bannedDependencies.html"&gt;Maven Enforcer Plugin&lt;/a&gt;. Add the plugin to your root project pom:
&lt;pre style="color:#800000;font-weight:normal;font-style:normal;"&gt;&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;1 &lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;project&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;2 &lt;/span&gt;  &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;build&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;3 &lt;/span&gt;    &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;plugins&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;4 &lt;/span&gt;      &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;plugin&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;5 &lt;/span&gt;        &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;org.apache.maven.plugins&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;groupId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;6 &lt;/span&gt;        &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;maven-enforcer-plugin&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;artifactId&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;7 &lt;/span&gt;        &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;1.0&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;version&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;8 &lt;/span&gt;        &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;executions&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;9 &lt;/span&gt;          &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;execution&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;10 &lt;/span&gt;            &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;id&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;enforce-banned-dependencies&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;id&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;11 &lt;/span&gt;            &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;goals&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;12 &lt;/span&gt;              &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;goal&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;enforce&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;goal&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;13 &lt;/span&gt;            &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;goals&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;14 &lt;/span&gt;            &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;configuration&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;15 &lt;/span&gt;              &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;rules&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;16 &lt;/span&gt;                &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;bannedDependencies&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;17 &lt;/span&gt;                  &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;excludes&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;18 &lt;/span&gt;                    &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;exclude&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;commons-logging&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;exclude&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;19 &lt;/span&gt;                    &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;exclude&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;cglib:cglib&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;exclude&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;20 &lt;/span&gt;                  &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;excludes&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;21 &lt;/span&gt;                &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;bannedDependencies&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;23 &lt;/span&gt;              &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;rules&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;24 &lt;/span&gt;              &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;fail&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;font-style:normal;"&gt;true&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;fail&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;25 &lt;/span&gt;            &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;configuration&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;26 &lt;/span&gt;          &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;execution&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;27 &lt;/span&gt;        &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;executions&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;28 &lt;/span&gt;      &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;plugin&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;29 &lt;/span&gt;    &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;plugins&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;30&lt;/span&gt; &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;build&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;31 &lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;project&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;As I mentioned, using the Enforcer plugin won&amp;#8217;t exclude the unwanted dependencies, it only will fail the build. Once that happened (and trust me, it will), you need to go and exclude them manually, as described in Stage 1 above.&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;p&gt;And we are done with Maven. Not fun? Switch your build tool!&lt;/p&gt;
&lt;h4&gt;Ivy&lt;/h4&gt;
&lt;p&gt;Well, comparing to Maven it&amp;#8217;s emabrassing how easy is to add global exclusion in Ivy. All you need to do is add exclude tag, and it will do the job for all the transitive dependencies, both in current and future use:&lt;/p&gt;
&lt;pre&gt;&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;1 &lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;dependencies&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;2 &lt;/span&gt;    &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;dependency &lt;/span&gt;&lt;span style="color:#0000ff;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;org=&lt;/span&gt;&lt;span style="color:#008000;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;"org.&lt;/span&gt;&lt;span style="color:#008000;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;springframework&lt;/span&gt;&lt;span style="color:#008000;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;" &lt;/span&gt;&lt;span style="color:#0000ff;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;name=&lt;/span&gt;&lt;span style="color:#008000;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;"spring-&lt;/span&gt;&lt;span style="color:#008000;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;webmvc&lt;/span&gt;&lt;span style="color:#008000;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;"&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;3 &lt;/span&gt;&lt;span style="color:#0000ff;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;rev=&lt;/span&gt;&lt;span style="color:#008000;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;"3.0.5.RELEASE" &lt;/span&gt;&lt;span style="color:#0000ff;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;conf=&lt;/span&gt;&lt;span style="color:#008000;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;"compile-&amp;gt;default"&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;4 &lt;/span&gt;    &lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;exclude &lt;/span&gt;&lt;span style="color:#0000ff;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;org=&lt;/span&gt;&lt;span style="color:#008000;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;"commons-logging"&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;5 &lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#000080;background-color:#efefef;font-weight:bold;font-style:normal;"&gt;dependencies&lt;/span&gt;&lt;span style="color:#000000;background-color:#efefef;font-weight:normal;font-style:normal;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Done.&lt;/p&gt;
&lt;h4&gt;Gradle&lt;/h4&gt;
&lt;p&gt;Since Gradle uses Ivy under the hood, here comes the same ease, but even groovier:&lt;/p&gt;
&lt;pre&gt;&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;1 &lt;/span&gt;    &lt;span style="color:#000000;font-weight:normal;font-style:normal;"&gt;configurations&lt;/span&gt; {
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;2 &lt;/span&gt;        &lt;span style="color:#000000;font-weight:normal;font-style:normal;"&gt;all&lt;/span&gt;*.exclude module: &lt;span style="color:#008000;font-weight:bold;font-style:normal;"&gt;'commons-logging'&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;3 &lt;/span&gt;        &lt;span style="color:#000000;font-weight:normal;font-style:normal;"&gt;all&lt;/span&gt;*.exclude group: &lt;span style="color:#008000;font-weight:bold;font-style:normal;"&gt;'cglib'&lt;/span&gt;, module: &lt;span style="color:#008000;font-weight:bold;font-style:normal;"&gt;'cglib-nodep'&lt;/span&gt;
&lt;span style="color:#800000;font-weight:normal;font-style:normal;"&gt;4 &lt;/span&gt;    }&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;That&amp;#8217;s all!&lt;/strong&gt; Now your code is bullet-proof from classloading conflicts and you can do nasty class-replacing stuff, for &lt;a title="Unified (as much as possible) logging using SLF4J" href="http://jbaruch.wordpress.com/2011/06/22/unified-logging-using-slf4j/"&gt;logging&lt;/a&gt; or pleasure.&lt;/p&gt;
&lt;br /&gt;Filed under: &lt;a href='http://blog.sadogursky.com/category/build/'&gt;Build&lt;/a&gt; Tagged: &lt;a href='http://blog.sadogursky.com/tag/gradle/'&gt;gradle&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/ivy/'&gt;ivy&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/maven2/'&gt;maven2&lt;/a&gt;, &lt;a href='http://blog.sadogursky.com/tag/maven3/'&gt;maven3&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jbaruch.wordpress.com/125/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jbaruch.wordpress.com/125/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jbaruch.wordpress.com/125/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jbaruch.wordpress.com/125/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jbaruch.wordpress.com/125/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jbaruch.wordpress.com/125/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jbaruch.wordpress.com/125/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jbaruch.wordpress.com/125/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jbaruch.wordpress.com/125/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jbaruch.wordpress.com/125/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jbaruch.wordpress.com/125/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jbaruch.wordpress.com/125/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jbaruch.wordpress.com/125/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jbaruch.wordpress.com/125/" /&gt;&lt;/a&gt; &lt;img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.sadogursky.com&amp;#038;blog=481424&amp;#038;post=125&amp;#038;subd=jbaruch&amp;#038;ref=&amp;#038;feed=1" width="1" height="1" /&gt;</description>
      <pubDate>Wed, 22 Jun 2011 01:39:00 CDT</pubDate>
      <guid isPermaLink="true">http://jbaruch.wordpress.com/?p=125</guid>
      <dc:creator>Baruch Sadogursky</dc:creator>
    </item>
    <item>
      <title>Small Issue with the Asset Pipeline</title>
      <link>http://projectautomationexperience.com/blog/david_bock/2011/06/small_issue_with_the_asset_pipeline</link>
      <description>&lt;p&gt;This is a small complaint about Rails 3.1, but its one I'm surprised I'm able to make at all.&lt;/p&gt;

&lt;p&gt;If you have been following the evolution of Rails, you know that years ago the framework adopted REST as one of its core principals (well, restful concepts - I'll leave it up to others to debate/defend the true purity of the implementation).  One of the core ideas behind REST is the idea that a url represents a unique resource, and that the mimetype/filename extension is used to negotiate the format that gets delivered.  for instance:&lt;/p&gt;

&lt;code&gt;
http://www.davebock.com/resume.html
&lt;/code&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;code&gt;
http://www.davebock.com/resume.pdf
&lt;/code&gt;

&lt;p&gt;should be the same underlying *thing*; what gets transferred is a representation of the thing in the format requested... in this case, my resume, as either html or pdf.&lt;/p&gt;

&lt;p&gt;Enter the new Rails Asset Pipeline, which is a fantastic piece of work in general.  In diving in and playing with it for the first time, I was trying to wrap my head around some of the conventions.  I generated a new rails project with v3.1rc4, and I hadn't added any of my own content yet.  I was looking at how everything under assets directory seems to be served up under the /assets/ url without much respect for the directory structure underneath it.  Out of the box, rails gives us several files that have default contents.  For instance:&lt;/p&gt;

&lt;code&gt;
http://localhost:3000/assets/application.css
&lt;/code&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;code&gt;
http://localhost:3000/assets/application.js
&lt;/code&gt;

&lt;p&gt;Compare that to my first example above.  These are the same url, but with different extensions - different "content negotiators"...  but they aren't serving up the same thing at all.  One could argue that they are two things designed to work together, but I don't think thats enough - the principal is violated - these are not the same thing, just in different formats, these are really much different things - one being code in the Javascript language meant to be used by your web application, and the other being a css file that contains all of the view/layout of your app.  the browser isn't saying, "Give me that same information, but in the .js format", the browser really is requesting a different asset.&lt;/p&gt;

&lt;p&gt;I like the asset pipeline, and I like the convention of treating all of these things as "first-class citizens" in their own assets directory under /app instead of as "a bunch of stuff" that happens to live under the /public directory - but I don't think this first-class citizenry has gone far enough - why aren't these things further scoped by the /images, /javascripts, and /stylesheets directory when referenced via url?&lt;/p&gt;</description>
      <pubDate>Mon, 20 Jun 2011 11:30:00 CDT</pubDate>
      <guid isPermaLink="true">http://blog.codesherpas.com/on_the_path/2011/06/small-issue-with-the-asset-pipeline.html</guid>
      <dc:creator>David Bock</dc:creator>
    </item>
  </channel>
</rss>

