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

<channel>
	<title>Sonatype Blog &#187; Tutorial</title>
	<atom:link href="http://blog.sonatype.com/people/tag/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sonatype.com/people</link>
	<description>Sonatype is transforming software development with tools, information and services that enable organizations to build better software, faster, using open-source components.</description>
	<lastBuildDate>Thu, 16 May 2013 18:53:09 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Benefits of a Repository Manager: Part III Continuous Build Deployment</title>
		<link>http://blog.sonatype.com/people/2010/08/benefits-of-a-repository-manager-part-iii-continuous-build-deployment/</link>
		<comments>http://blog.sonatype.com/people/2010/08/benefits-of-a-repository-manager-part-iii-continuous-build-deployment/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 13:46:30 +0000</pubDate>
		<dc:creator>Tim O'Brien</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[ant]]></category>
		<category><![CDATA[builds]]></category>
		<category><![CDATA[continuous]]></category>
		<category><![CDATA[Hudson]]></category>
		<category><![CDATA[repository]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=5914</guid>
		<description><![CDATA[In the previous post in this series I discussed three compelling ways in which a repository manager can benefit the development cycle. It proxies artifacts locally, it is optimized to store binary artifacts, and it facilitates a new level of collaboration and agility that isn&#8217;t possible when your SCM is only way for workgroups to [...]]]></description>
				<content:encoded><![CDATA[<p>In the previous post in this series I discussed three compelling ways in which a repository manager can benefit the development cycle.   It proxies artifacts locally, it is optimized to store binary artifacts, and it facilitates a new level of collaboration and agility that isn&#8217;t possible when your SCM is only way for workgroups to collaborate.   In this post, I&#8217;m going to talk about how a repository manager works in concert with a continuous integration server like Hudson or Bamboo.</p>

<p><span id="more-5914"></span></p>

<p><a href="http://www.sonatype.com/people/wp-content/uploads/2010/08/ci-builds.png"><img class="aligncenter size-full wp-image-5915" title="ci-builds" src="http://www.sonatype.com/people/wp-content/uploads/2010/08/ci-builds.png" alt="" width="337" height="147" /></a></p>

<p>First, the how, what, and when of a continuous integration server.  Continuous integration (CI) servers are an established fact of of modern development infrastructure.   It is a server which, for the most part, waits and watches.   It keeps a vigilant eye on your source control system and jumps into action every time it sees a code change.    When code changes, your CI system is usually configured to run the entire build, execute all of your unit and integration tests, and send out an email to every developer if it identifies a defect or a failed test.</p>

<p>It does this so that you will have an easier time identifying where a particular problem was introduced to the source code.   If John checks in some bad code, the CI system runs the build immediately, and about 30 minutes later, everyone in the group receives an email with the subject header &#8220;John just broke the build&#8221;.   It is a great way to identify errors, and it is also a great way to motivate developers to test locally before committing to a source control system as no one likes to be the reason for a build failure email.</p>

<p>Running a CI server is more than &#8220;just a good idea&#8221;.  Once your system reaches a certain level of complexity you can&#8217;t scale a system without commiting to continuous integration and testing.   If you don&#8217;t have continuous integration, you end up having to put all development on hold each time you want to perform a release.   If you don&#8217;t build, test, and deploy your system on a regular basis &#8211; if it isn&#8217;t something that is well rehearsed, integration becomes a time consuming nightmare of manual testing and builds that often leads to inconsistent builds.   This is especially true if your development effort spans multiple systems and multiple development workgroups.   You run a CI system because building, testing, and deploying your system should be automatic: it should be as trivial as pressing a button.</p>

<p>The concept of a CI server is only slightly more established than a repository manager, and very often you will see that an organization has identified the need for a CI server before they&#8217;ve identified the need for a repository manager.   If you are coding a complex system, there is a very good chance that you are already running a CI server.  The most popular servers out there are Hudson, Bamboo, and CruiseControl.   While the connection between CI servers and repository managers might not be immediately obvious, when used together they can introduce some new possibilities for the way you develop your systems.</p>

<h2>Continuous Publishing</h2>

<p>When you have a system to continuously build your code, you also have a system that can continuously publish SNAPSHOT artifacts to a repository manager to enable a more granular approach to development.   What do I mean by &#8220;a more granular approach to development&#8221;?  To answer that question, let&#8217;s take a look at a complex multi-module project using the example of the eCommerce group from the previous post in this series.</p>

<p><a href="http://www.sonatype.com/people/wp-content/uploads/2010/08/ecom-multimod.png"><img class="aligncenter size-full wp-image-5918" title="ecom-multimod" src="http://www.sonatype.com/people/wp-content/uploads/2010/08/ecom-multimod.png" alt="" width="434" height="569" /></a></p>

<p>Assume you have a new programmer starting tomorrow.   Instead of throwing him at the entire forty-thousand lines of code, you would like to be able to give that developer a small, easy to digest task.    You want this developer to add support for PayPal&#8217;s Adaptive Payments API in your eCommerce system.  That&#8217;s it.   You don&#8217;t want them to be distracted by the overwhelming scope of the project, and you certainly can&#8217;t afford for them to take a three month voyage through your project&#8217;s code before they start contributing to the effort.   Deadlines are tight, and you don&#8217;t have enough people on your team.   It is important that new hires start programming as soon as they walk in the door.</p>

<p>Without a repository manager hooked up to a continuous integration server, if you try to checkout just the ecom-paypal project, the build is going to fail because it will try to download dependencies from a repository manager.   In the case of the ecom-paypal project, assume that the dependency graph looks like this.</p>

<p><a href="http://www.sonatype.com/people/wp-content/uploads/2010/08/ecom-multimod-dep.png"><img class="aligncenter size-full wp-image-5919" title="ecom-multimod-dep" src="http://www.sonatype.com/people/wp-content/uploads/2010/08/ecom-multimod-dep.png" alt="" width="448" height="191" /></a></p>

<p>When you have a repository manager and a continuous integration server, you can configure your continuous integration server to publish SNAPSHOT artifacts (in-progress SNAPSHOT binaries) to your repository manager.   This will allow you to just check out a single, isolated portion of a much larger multi-module project.</p>

<p>Without a repository manager, trying to build version 1.3-SNAPSHOT of ecom-paypal in isolation is going to generate errors because you are forced to checkout the entire codebase to build and install all of the dependencies in your local repository.   With a repository manager, SNAPSHOT artifacts are being continuously published because Hudson is checking you SCM every few minutes and building the latest code.   When you run the ecom-paypal module&#8217;s build in isolation, Maven is going to download the most recent SNAPSHOT.</p>

<p>Without a repository manager, your new developer is going to have to download the entire codebase and run a large time-consuming build.   With a repository manager you can work on specific components of a larger multi-module project.    This ability to divide and conquer your codebase comes in very handy when you need a consultant to take a look at a specific problem, or when you need to look at a coding problem in isolation.</p>

<p>When you continuously publish build artifacts to a repository manager, you move away from the single monolithic project build and toward a project layout and architecture that lends itself to modularization.</p>

<p>In tomorrow&#8217;s post: How a Repository Manager decouples deployments from source code, and what that means for developer operations.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2010/08/benefits-of-a-repository-manager-part-iii-continuous-build-deployment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Benefits of a Repository Manager: Part I</title>
		<link>http://blog.sonatype.com/people/2010/08/benefits-of-a-repository-manager-part-i/</link>
		<comments>http://blog.sonatype.com/people/2010/08/benefits-of-a-repository-manager-part-i/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 13:00:24 +0000</pubDate>
		<dc:creator>Tim O'Brien</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[Hudson]]></category>
		<category><![CDATA[repository manager]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=5897</guid>
		<description><![CDATA[Whenever I speak to someone doing Java development, I always ask if they are using a repository manager. Repository managers are still an emerging technology, but I&#8217;ve noticed a consistent trend: more and more developers view a repository manager as an essential part of development infrastructure. This certainly wasn&#8217;t the case just two years ago, [...]]]></description>
				<content:encoded><![CDATA[<p>Whenever I speak to someone doing Java development, I always ask if they are using a repository manager. Repository managers are still an emerging technology, but I&#8217;ve noticed a consistent trend: more and more developers view a repository manager as an essential part of development infrastructure. This certainly wasn&#8217;t the case just two years ago, and I think that the big motivator behind this trend is that the quality and stability of Maven Central has improved remarkably because of the efforts of people like Brian Fox and others who are focused on making the service more stable.</p>

<p>Another reason why we&#8217;ve seen more adoption is that most developers understand the benefits of using a tool like Maven for automatic dependency management. In 2005, it was common to see projects store binary JARs alongside source code in projects. In 2010, you rely on the repository and the metadata it contains. If you use a library like Guice, you&#8217;ll add a dependency on the artifact and let your build tool take care of the details. To do otherwise would be to commit yourself to a manual work updating JARs and testing dependencies each time a new version of an external library is released.</p>

<p>Despite the increasing prevalence of repository managers, I still stumble upon workgroups and organizations that haven&#8217;t heard of repository management. When you ask if they are using a repository manager, they might think you are referring to Subversion or source control. This series of posts is a high-level overview of the main benefits of repository management. If you are trying to convince someone to start using a repository manager, the next few blog posts are for you.
<span id="more-5897"></span></p>

<h2>Repository Management: The Big Picture</h2>

<p><a href="http://www.sonatype.com/people/wp-content/uploads/2010/08/full-picture.png"><img class="aligncenter size-full wp-image-5898" title="full-picture" src="http://www.sonatype.com/people/wp-content/uploads/2010/08/full-picture.png" alt="" width="488" height="272" /></a></p>

<p>Compare the diagram shown above with the diagram shown below. In the next few posts, I am going to emphasize the specific benefits of using a repository manager. Specifically, I&#8217;m going to talk about:</p>

<ul>
    <li>How a repository manager changes the development cycle</li>
    <li>How continuous integration is used to continuously publish internal build artifacts</li>
    <li>How a repository manager simplifies the process of building and deploying systems to production</li>
    <li>How a repository manager can act as a gateway between vendors and external partners</li>
</ul>

<p><a href="http://www.sonatype.com/people/wp-content/uploads/2010/08/old-school.png"><img class="aligncenter size-full wp-image-5899" title="old-school" src="http://www.sonatype.com/people/wp-content/uploads/2010/08/old-school.png" alt="" width="395" height="272" /></a></p>

<h2>When you don&#8217;t use a Repository Manager</h2>

<p>Before I get started on the benefits of repository management, I want to talk about the realities you face when you don&#8217;t use a repository manager. Here are some common anti-patterns when you don&#8217;t use a repository manager:</p>

<ul>
    <li><strong>All of your developers download artifacts directly from public repositories.</strong> A new developer starts on a Monday. That developer will spend an hour downloading a massive library of dependencies from Maven Central. Worse, if Maven Central happens to be down that day, they will be out of luck entirely.</li>
    <li><strong>Proprietary or Vendors libraries are passed around, from developer to developer.</strong> If you don&#8217;t use a repository manager, how do you distribute the Oracle JDBC driver? Maybe you place it in a shared file system and tell people to download it and install it in ~/.m2/repository. More likely, developers just pass this JAR around as an email attachment with some ad-hoc instructions.</li>
    <li><strong>JARs are checked into source control</strong>. If you don&#8217;t use a tool like Maven, which knows how to download artifacts from a remote repository, you might be following the very common pattern of checking binary dependencies and libraries into source control. I&#8217;ve seen many instances of companies creating ad-hoc JAR repositories and checking these repositories into source control, only to version and branch these static binary files with every release.</li>
    <li><strong>The source control repository is used to store <em>everything</em></strong> from source code to binary builds. Because there is no repository designed to store binaries, developers start to use tools like Subversion to keep track of binaries. As time passes, the Subversion repository becomes an ad-hoc file system for files that have no business in an SCM.</li>
    <li><strong>The continuous integration server depends on public repositories</strong>. When you change your build or add a new dependency, your CI system downloads dependencies from the public repo. It depends on the availability of this public resource to run builds.</li>
    <li><strong>Production deployments have to run the entire build</strong>, from start to finish, to generate binaries for deployment. When a build is tested and then ultimately pushed to production, the build and deployment scripts checkout source code, run the build, and deploy the resulting binaries to production systems.</li>
    <li><strong>Sharing source code with external partners means granting them access to your SCM.</strong> Since there is no established mechanism for publishing source or binary artifacts, the only way to share code with partners is to either send an archive of your source, or provide them with direct access to your SCM.</li>
</ul>

<p>The general theme in all of these anti-patterns is that either your systems depend on public resources, or they all depend on the SCM system as a central collaboration point. In the next few posts, I&#8217;m going to detail how using a repository manager provides a solution for each of these issues. I&#8217;ll go into why each of these anti-patterns is a bad idea, and how you can use Maven, Nexus, and Hudson together to solve these problems and create a more efficient software development effort.</p>

<p><em>Stay tuned for the next post: Caching and Collaborating.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2010/08/benefits-of-a-repository-manager-part-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maven Dependency Resolution &#8211; A Repository Perspective</title>
		<link>http://blog.sonatype.com/people/2009/12/maven-dependency-resolution-a-repository-perspective/</link>
		<comments>http://blog.sonatype.com/people/2009/12/maven-dependency-resolution-a-repository-perspective/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 15:20:37 +0000</pubDate>
		<dc:creator>Juven Xu</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=3492</guid>
		<description><![CDATA[Dependencies and repositories are central to Maven. Most people approach Maven as a tool in a very large stack of technology and they might not have the time to dig into the details. You might be using Eclipse, Maven, Nexus, Hudson, in addition to the various libraries and servers that are involved in your development [...]]]></description>
				<content:encoded><![CDATA[<p>Dependencies and repositories are central to Maven.  Most people approach Maven as a tool in a very large stack of technology and they might not have the time to dig into the details.   You might be using Eclipse, Maven, Nexus, Hudson, in addition to the various libraries and servers that are involved in your development environment, and Maven&#8217;s dependency management is often so effective at hiding the details of repositories and dependencies that you take some of the complexity behind the scenes for granted.   This post explains how dependencies and repositories work together for people who are interested some of the details that make dependency management in Maven &#8220;just work&#8221;.</p>

<p><span id="more-3492"></span></p>

<p>First of all, we need to know the default repository layout, which affects the repository path of each artifact. The related Maven source code is easy to understand, here it is:</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">char</span> PATH_SEPARATOR <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/'</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">char</span> GROUP_SEPARATOR <span style="color: #339933;">=</span> <span style="color: #0000ff;">'.'</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">char</span> ARTIFACT_SEPARATOR <span style="color: #339933;">=</span> <span style="color: #0000ff;">'-'</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> pathOf<span style="color: #009900;">&#40;</span> Artifact artifact <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    ArtifactHandler artifactHandler <span style="color: #339933;">=</span> artifact.<span style="color: #006633;">getArtifactHandler</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    StringBuilder path <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> StringBuilder<span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">128</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    path.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> formatAsDirectory<span style="color: #009900;">&#40;</span> artifact.<span style="color: #006633;">getGroupId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> PATH_SEPARATOR <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    path.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> artifact.<span style="color: #006633;">getArtifactId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> PATH_SEPARATOR <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    path.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> artifact.<span style="color: #006633;">getBaseVersion</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> PATH_SEPARATOR <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    path.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> artifact.<span style="color: #006633;">getArtifactId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> ARTIFACT_SEPARATOR <span style="color: #009900;">&#41;</span>.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> artifact.<span style="color: #006633;">getVersion</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> artifact.<span style="color: #006633;">hasClassifier</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      path.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> ARTIFACT_SEPARATOR <span style="color: #009900;">&#41;</span>.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> artifact.<span style="color: #006633;">getClassifier</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> artifactHandler.<span style="color: #006633;">getExtension</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> artifactHandler.<span style="color: #006633;">getExtension</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      path.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> GROUP_SEPARATOR <span style="color: #009900;">&#41;</span>.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span> artifactHandler.<span style="color: #006633;">getExtension</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">return</span> path.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> formatAsDirectory<span style="color: #009900;">&#40;</span> <span style="color: #003399;">String</span> directory <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> directory.<span style="color: #006633;">replace</span><span style="color: #009900;">&#40;</span> GROUP_SEPARATOR, PATH_SEPARATOR <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>


<p>Take TestNG as an example, assume the artifact coordinate is groupId=org.testng, artifactId=testng, version=4.8, classifier=jdk15, and packaging=jar, the above code runs like this:</p>

<ol>
    <li>Calcuate the repository path from the groupId, replace the groupId separator dot with path separator slash, and append another path separator. So, <em>org.testng</em> becomes <em>org/testng/</em>.</li>
    <li>Append the artifactId and a path separator. Since in this example the artifactId is <em>testng</em>, so the path becomes <em>org/testng/testng/</em>.</li>
    <li>Append the artifact&#8217;s base version and a path separator. For release artifacts, base version is the version, for snapshots, timestamp will be converted to SNAPSHOT to get the base version. In this example, the base version is <em>5.8</em>, so the path becomes <em>org/testng/testng/5.8/</em>.</li>
    <li>Append the artifactId, a artifact separator hyphen, and the version. Now, the path becomes <em>org/testng/testng/5.8/testng-5.8</em>.</li>
    <li>If the artifact has a classifier, append a artifact separator and the classifier. In this example the classifier is jdk15, so the path becomes <em>org/testng/testng/5.8/testng-5.8-jdk15</em>.</li>
    <li>Finally, get the artifact extension from artifactHandler. Each packaging type has its own artifactHandler, so the extension is determined by packaging, for default packaging type jar, the extension is also jar. Append a groupId separator dot, and the extension. So the path is finally <em>org/testng/testng/5.8/testng-5.8-jdk15.jar</em>.</li>
</ol>

<p>Now we know how Maven gets the repository path from artifact coordinate, but this is not the whole story. What if the artifact does not exist in local repository? what if the version of artifact is SNAPSHOT?  How does Maven know where and how to get the latest SNAPSHOT?</p>

<p>When Maven resolves a dependency from a repository, these are the basic steps it follows:</p>

<ol>
    <li>If the scope of this dependency is <em>system</em>, simply resolve it from local file system.</li>
    <li>Try to find the dependency from local repository, resolve it if it&#8217;s found.</li>
    <li>If the version of the dependency is explicit and non-SNAPSHOT, iterate though the remote repositories to download it, and resolve it if it&#8217;s found.</li>
    <li>(For version RELEASE or LATEST) When it&#8217;s required, iterate all the remote repositories to get <em>groupId/artifactId/maven-metadata.xml</em> and merge them with the local one.</li>
    <li>(For version RELEASE or LATEST) Use the merged metadata to construct an explicit non-snapshot version, resolve it if it&#8217;s found locally, otherwise download it from remote repository.</li>
    <li>(For SNAPSHOT version) When it&#8217;s required, iterate though the remote repositories to get <em>groupId/artifactId/version/maven-metadata.xml</em> and merge them with the local one.</li>
    <li>(For SNAPSHOT version) Use the merged metadata to construct an explicit snapshot version, resolve it if it&#8217;s found locally, otherwise download it from remote repository.</li>
    <li>(For SNAPSHOT version) If the resolved snapshot version is of timestamp style, like <em>1.4.1-20091104.121450-121</em>,  copy the file to a non-timestamp style, like <em>1.4.1-SNAPSHOT</em>, and use this file.</li>
</ol>

<p>A few notes:</p>

<p><strong>In step 4 and 6:</strong> &#8216;when it&#8217;s required&#8217; means release/snapshot must be enabled for the repository, and repository updatePolicy is satisfied, or force update is enabled by -U options.</p>

<p><strong>In step 5:</strong> In maven 2, LATEST will be constructed to the real latest version, no matter it&#8217;s snapshots or not, but in maven 3, only the latest non-snapshot version will be used.</p>

<p><strong>in step 4:</strong> a typical groupId/artifactId/maven-metadata.xml is like this:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!--?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?--&gt;</span>
&nbsp;
  org.sonatype.nexus
  nexus
&nbsp;
    1.4.2-SNAPSHOT
    1.4.0
&nbsp;
      1.3.5
      1.3.6
      1.3.7-SNAPSHOT
      1.4.0-SNAPSHOT
      1.4.0
      1.4.0.1-SNAPSHOT
      1.4.1-SNAPSHOT
      1.4.1.1-SNAPSHOT
      1.4.2-SNAPSHOT
&nbsp;
    20091214221557</pre></div></div>


<p>All the available versions in this directory are listed in order.  The latest element points to the latest version, and the release element points to the latest release version. With the help of this file, Maven knows what the latest release version is.</p>

<p><strong>In step 6:</strong> a typical groupId/artifactId/version/maven-metadata.xml is like this:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!--?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?--&gt;</span>
&nbsp;
  org.sonatype.nexus
  nexus
  1.4.2-SNAPSHOT
&nbsp;
      20091214.221414
      13
&nbsp;
    20091214221558</pre></div></div>


<p>The timestamp and buildnumber of the latest snapshot is listed, so Maven can understand what the latest snapshot artifact file is. In this case, it is <em>nexus-1.4.2-20091214.221414-13.pom</em>.</p>

<p>Now that you are familiar with the process Maven uses to resolve dependencies, calculate dependency paths, and resolve conflicts you can refer to this post whenever you have an unexpected failure resolving a dependency.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sonatype.com/people/2009/12/maven-dependency-resolution-a-repository-perspective/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
