<?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; plugins</title>
	<atom:link href="http://www.sonatype.com/people/tag/plugins/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.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, 09 Feb 2012 15:48:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Tame Your Dependencies With Free Eclipse Plugin</title>
		<link>http://www.sonatype.com/people/2011/07/tame-your-dependencies-with-free-eclipse-plugin/</link>
		<comments>http://www.sonatype.com/people/2011/07/tame-your-dependencies-with-free-eclipse-plugin/#comments</comments>
		<pubDate>Thu, 28 Jul 2011 15:28:29 +0000</pubDate>
		<dc:creator>Terry Bernstein</dc:creator>
				<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Insight]]></category>
		<category><![CDATA[Sonatype]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=8791</guid>
		<description><![CDATA[Sonatype recently released a free beta version of the Sonatype Insight Plugin for Eclipse that allows you to more efficiently manage and select Java components.  It is part of the Sonatype Insight product line that helps organizations take advantage of open source-based development while improving quality and reducing security and licensing risks. We want to [...]]]></description>
			<content:encoded><![CDATA[<p>Sonatype recently released a free beta version of the Sonatype Insight Plugin for Eclipse that allows you to more efficiently manage and select Java components.  It is part of the Sonatype Insight product line that helps organizations take advantage of open source-based development while improving quality and reducing security and licensing risks.</p>

<div id="attachment_8793" class="wp-caption alignright" style="width: 445px"><a href="http://www.sonatype.com/people/wp-content/uploads/2011/07/Component-versions-in-Eclipse-Tool.png"><img class="size-full wp-image-8793   " title="Component versions in Development Insight for Eclipse" src="http://www.sonatype.com/people/wp-content/uploads/2011/07/Component-versions-in-Eclipse-Tool.png" alt="Screen shot of component versions display in Development Insight for Eclipse" width="435" height="153" /></a><p class="wp-caption-text">See what components are used,  which versions, and when updates are available</p></div>

<p>We want to make component based development as easy as possible by providing you the tools to choose the right components from the beginning to speed development, improve quality, and reduce costly rework. This plugin, the first of a series of development tools, helps you tame the issues typically associated with utilizing open source Java components, including:</p>

<ul>
    <li>Determining when new component versions are available and making informed update decisions</li>
    <li>Understanding what versions of each component are used in your project</li>
    <li>Identifying where specific components are used</li>
    <li>Updating components throughout your project</li>
</ul>

<p>The plugin is build tool agnostic, and so works with all Java projects in general (Java, PDE, Maven, etc.).</p>

<p>This is just the beginning. We’ll be adding features to help you choose components that meet your security, quality, and licensing standards by providing useful information about each component right in the IDE.  For example, we’ll alert you when a component, or one of its dependencies has known security vulnerabilities. You’ll also be able to tell how each component or dependency is licensed without having to hunt through the code yourself.</p>

<p>So tame your dependencies today and get the <a href="http://www.sonatype.com/Products/Sonatype-Insight/Development-Insight/Development-Insight-for-Eclipse">Sonatype Insight Plugin for Eclipse</a>.</p>

<p>&nbsp;</p>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2011/07/tame-your-dependencies-with-free-eclipse-plugin/&via=SonatypeCM&text=Tame Your Dependencies With Free Eclipse Plugin&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2011/07/tame-your-dependencies-with-free-eclipse-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Use Aether in Maven Plugins</title>
		<link>http://www.sonatype.com/people/2011/01/how-to-use-aether-in-maven-plugins/</link>
		<comments>http://www.sonatype.com/people/2011/01/how-to-use-aether-in-maven-plugins/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 14:50:18 +0000</pubDate>
		<dc:creator>bbentmann</dc:creator>
				<category><![CDATA[Aether]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=6838</guid>
		<description><![CDATA[When developing plugins for Maven 3.0 plugin developers that need to perform dependency resolution have a choice: they can continue to use the Maven 2.x API, or they can use the new Maven 3 API which makes use of Aether. In this post, I&#8217;m going to walk through some of the API features that are [...]]]></description>
			<content:encoded><![CDATA[<p>When developing plugins for Maven 3.0 plugin developers that need to perform dependency resolution have a choice: they can continue to use the Maven 2.x API, or they can use the new Maven 3 API which makes use of <a rel="nofollow" href="http://aether.sonatype.org/" target="_blank">Aether</a>.   In this post, I&#8217;m going to walk through some of the API features that are now available to plugin developers in Aether.</p>

<p>If your plugin needs to be compatible with Maven 2.x, take a look at the sources of <a rel="nofollow" href="http://maven.apache.org/plugins/maven-dependency-plugin/source-repository.html" target="_blank">Maven Dependency Plugin</a>.   This example provides a sophisticated example of using the Maven 2.x dependency resolution API. But if legacy Maven support is of no concern to you, read on and see how the Maven 3.x API handles the job.</p>

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

<h2>Aether Plugin Dependencies</h2>

<p>To make use of the new Maven 3.x Plugin API add the following dependencies to your plugin project&#8217;s POM:</p>

<script src="https://gist.github.com/777716.js?file=aether-dependencies.xml"></script>

<p>The dependency on <tt>maven-plugin-api</tt> shouldn&#8217;t be surprising &#8211; the more interesting bits are <tt>aether-api</tt> and <tt>aether-util</tt>. Depending on your use case, the latter dependency might not be required for your plugin given <tt>aether-util</tt> is just a collection of utility classes. For our example however, it will be handy to have <tt>org.sonatype.aether.util.artifact.DefaultArtifact</tt> around.</p>

<h2>Mojo Parameters</h2>

<p>Now that the plugin build path is set up, we can continue to add some parameters to our plugin that will grab the repository system:</p>

<script src="https://gist.github.com/777719.js?file=MyMojo-aether-parameters.java"></script>

<p>In contrast to Maven 2.x, a single component of type <tt>RepositorySystem</tt> is sufficient for all resolution work. This repository system generally takes a request bean as input and hands back a result bean. When performing multiple repository operations, some inputs tend to be the same like the local repository, the offline mode, proxies etc. These configuration values are represented by the <tt>RepositorySystemSession</tt>.</p>

<p>The remote repositories to resolve from are always specific to a certain operation. For our example, we&#8217;re going to use the remote plugin repositories of the current project. Alternatively, the expression <tt>$&#123;project.remoteProjectRepositories&#125;</tt> is available to grab the project dependency repositories. Which set of remote repositories to use depends on the kind of artifacts the plugin is going to resolve. Artifacts that are compile/runtime/test dependencies of a project need to be resolved from <tt>$&#123;project.remoteProjectRepositories&#125;</tt>. Plugins or other artifacts that merely support the build need to be resolved from <tt>$&#123;project.remotePluginRepositories&#125;</tt>.</p>

<h2>Mojo Execution</h2>

<p>Equipped with the plugin parameters shown in the previous section, we can start to do some real work with project dependencies:</p>

<script src="https://gist.github.com/777724.js?file=gistfile1.java"></script>

<p>This code snippet resolves a single artifact that is hard-coded here for the sake of conciseness. By employing other methods of the <tt>repoSystem</tt> transitive resolution or version query can be performed as well.</p>

<p>Tip: To help with the common task of transitively resolving project dependencies, the <tt>maven-core</tt> artifact provides the component <tt>org.apache.maven.project.ProjectDependenciesResolver</tt>.</p>

<p>A complete plugin project ready to run and play with can be found in our Git repo at <tt><a rel="nofollow" href="https://github.com/sonatype/aether-demo-maven-plugin" target="_blank">https://github.com/sonatype/aether-demo-maven-plugin</a></tt>.</p>

<p>A final note to avoid confusion when experimenting with the new API: Unlike the Maven 2.x API, <tt>Artifact</tt> instances in Aether are immutable. As such the result of a resolution operation returns new <tt>Artifact</tt> instances. That is why it is essential that the log statement above uses <tt>result.getArtifact().getFile()</tt> and not <tt>artifact.getFile()</tt>.</p>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2011/01/how-to-use-aether-in-maven-plugins/&via=SonatypeCM&text=How to Use Aether in Maven Plugins&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2011/01/how-to-use-aether-in-maven-plugins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#039;s in Maven 3.0 for Plugin Authors?</title>
		<link>http://www.sonatype.com/people/2010/11/whats-in-maven-3-0-for-plugin-authors/</link>
		<comments>http://www.sonatype.com/people/2010/11/whats-in-maven-3-0-for-plugin-authors/#comments</comments>
		<pubDate>Wed, 17 Nov 2010 17:14:11 +0000</pubDate>
		<dc:creator>bbentmann</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[developer]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=6490</guid>
		<description><![CDATA[While Maven 3 is a dramatic improvement over Maven 2 from the perspective of performance, extensibility, and architecture, most end-users are motivated by plugins. This has been true about Maven from the beginning, while the framework has value, it is the plugins that make the difference. This blog focuses on the changes that are of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sonatype.com/people/wp-content/uploads/2009/10/maven.png"><img src="http://www.sonatype.com/people/wp-content/uploads/2009/10/maven.png" alt="" title="maven" width="250" height="72" class="alignright size-full wp-image-3145" /></a></p>

<p>While Maven 3 is a dramatic improvement over Maven 2 from the perspective of performance, extensibility, and architecture, most end-users are motivated by plugins.   This has been true about Maven from the beginning, while the framework has value, it is the plugins that make the difference.  This blog focuses on the changes that are of interest to plugin authors.</p>

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

<h2>Accessing Project Dependencies</h2>

<p>The easiest way for a plugin to get the entire set of transitive dependencies for a project is the mojo annotation @requiresDependencyResolution. This annotation is configured with one of the values: compile, runtime or test, which denote the dependency scope a plugin is interested in. What has been proven troublesome is the subtle fact that the runtime classpath is not a superset of the compile classpath, i.e. dependencies of scope provided and system are not included in the runtime classpath.</p>

<p>Now, what shall plugin authors do that need to inspect the union of the compile and runtime classpaths? So far, the answer was either to request the test classpath or to programmatically do dependency resolution with the proper scope filter. Neither of these two approaches are really attractive for one reason or the other. So we eventually added support for a new annotation value in Maven 3.0, compile+runtime, that ensures project dependencies with the scopes compile, runtime, provided and system get resolved.</p>

<h2>Requiring Dependency Collection</h2>

<p>While we are at dependency resolution, Maven 3.0 also introduces the new annotation @requiresDependencyCollection. Admittedly, the name of this new annotation differs only slightly from the existing @requiresDependencyResolution annotation but there&#8217;s a rather important difference regarding the effect.</p>

<p>Dependency resolution consists of two phases. Phase one is determining the coordinates of all the transitive dependencies, phase two is getting the files for these artifacts which potentially involves downloading them. If one is only interested in phase one, we talk about dependency collection. In more detail, if a plugin goal declares @requiresDependencyCollection compile, it can inspect all transitive compile time dependencies of the project via MavenProject.getArtifacts(). But unlike @requiresDependencyResolution, the returned artifact instances might be unresolved, i.e. have no file associated with them.</p>

<p>It might seem odd to have unresolved artifacts but let me try to sketch the use cases that motivate this. While unresolved artifacts can not be used to create classpaths, they still allow a plugin to inspect the set of transitive dependencies, look for unwanted artifacts, check versions etc. If that reminds you of the Maven Release Plugin or the Maven Enforcer Plugin, great. Those plugins and others are usually invoked in very early lifecycle phases of the build, in particular, before any artifacts have been packaged or even any classes have been compiled. If those plugins try to resolve dependencies during a multi-module build with inter-project dependencies, they can&#8217;t succeed, what hasn&#8217;t been built yet cannot be resolved.</p>

<p>In Maven 2.x, there&#8217;s a hack that tolerates resolution errors if all of the missing artifacts are in the reactor but it still leaves your build with an ugly warning and the plugin in question with unsatisfied requirements. @requiresDependencyCollection is the answer to this situation and will help to eventually fix some long-standing issues in the previously-mentioned plugins. So if your plugin doesn&#8217;t need the actual files but only the coordinates of the project dependencies, consider to use the new annotation when targetting Maven 3.0 as a prerequisite.</p>

<h2>Writing Thread-safe Maven Plugins</h2>

<p>Related to the new support for <a href="https://cwiki.apache.org/confluence/display/MAVEN/Parallel+builds+in+Maven+3">parallel building in Maven 3.0</a>, there&#8217;s also a new mojo annotation @threadSafe. Right now, this annotation is nothing more than an informative suggestion. When Maven 3.0 is asked to perform a parallel build and encounters a plugin that isn&#8217;t marked as thread-safe, it will print a <b>prominent warning</b> that your build might fail as historically, plugin authors assumed a sequential execution and, as such, didn&#8217;t code with concurrency and thread safety in mind.</p>

<p>Unlike the previously mentioned extension to the Mojo API, this new annotation can be safely added to a plugin that targets Maven 2.x as runtime. So once you have reviewed your code and possibly adjusted it to support concurrent mojo execution, feel free to add this annotation to disable the build warning from Maven 3.0.  In addition to disabling the warning, the generated plugin site will also indicate that the goal supports parallel builds.</p>

<h2>Using Generics with Maven Plugins</h2>

<p>Given that Maven 2.2.x already requires Java 1.5 to run, more and more plugins are moving to Java 1.5 as well. To enable the benefits of Java 1.5, the Maven API has been updated to use generics, thereby easing plugin coding. Furthermore, Maven 3.0 allows to use enums for plugin configuration parameters.</p>

<h2>Fixes to the Classloader Hierarchy</h2>

<p>The last change I want to mention is the reworked class loader hierarchy. Build extensions can now contribute additional APIs and components that other plugins can utilize during the build. The APIs and components contributed by extensions are shared across all projects using the same extension which allows plugins to easily exchange domain-specific data structures during the build, e.g. via MavenProject.getContextValue() or via some stateful singleton from the extension. If that sounds interesting to you, have a look at the wiki article <a href="https://cwiki.apache.org/confluence/display/MAVEN/Maven+3.x+Class+Loading">Maven 3.x Class Loading</a> which describes the revised class loading in more depth.</p>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2010/11/whats-in-maven-3-0-for-plugin-authors/&via=SonatypeCM&text=What&#039;s in Maven 3.0 for Plugin Authors?&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2010/11/whats-in-maven-3-0-for-plugin-authors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nexus 1.5.0 Highlights: Open Sourcing Nexus LDAP Integration</title>
		<link>http://www.sonatype.com/people/2010/01/nexus-1-5-0-highlights-open-sourcing-nexus-ldap-integration/</link>
		<comments>http://www.sonatype.com/people/2010/01/nexus-1-5-0-highlights-open-sourcing-nexus-ldap-integration/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 09:00:37 +0000</pubDate>
		<dc:creator>Brian Demers</dc:creator>
				<category><![CDATA[Nexus]]></category>
		<category><![CDATA[Sonatype]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=4109</guid>
		<description><![CDATA[With the 1.5.0 release of Nexus, Sonatype is opening up the current LDAP features in Pro, and making them a part of Nexus Open Source.  Starting with this release, Nexus Open Source users will be able to integrate with LDAP, Active Directory, and Atlassian Crowd servers (via LDAP).  Nexus is the only repository manager with [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sonatype.com/people/wp-content/uploads/2010/01/nexus-small.png"><img class="alignright size-full wp-image-3683" title="nexus-small" src="http://www.sonatype.com/people/wp-content/uploads/2010/01/nexus-small.png" alt="" width="250" height="62" /></a>With the 1.5.0 release of Nexus, Sonatype is opening up the current LDAP features in Pro, and making them a part of Nexus Open Source.  Starting with this release, Nexus Open Source users will be able to integrate with LDAP, Active Directory, and Atlassian Crowd servers (via LDAP).  Nexus is the only repository manager with both Authentication AND Authorization (group / role mapping) via LDAP and now this integration is free for all to use.</p>

<p>As we transition this feature to Nexus Open Source, we are also announcing a new Nexus Enterprise LDAP plugin that will support more advanced deployment use cases including support for federated LDAP servers and more intelligent caching of authentication information.<span id="more-4109"></span></p>

<p>Features included in the newly open-source Nexus Professional LDAP plugin:</p>

<ul>
    <li><a rel="nofollow" href="http://www.sonatype.com/books/nexus-book/reference/ldap-sect-user-group-mapping.html#ldap-sect-mapping-active-directory">Active Directory Support<sup><img src="https://docs.sonatype.com/images/icons/linkext7.gif" border="0" alt="" width="7" height="7" align="absmiddle" /></sup></a></li>
    <li>Authentication via Bind, SASL, or attribute</li>
    <li>Ability to <a rel="nofollow" href="http://www.sonatype.com/books/nexus-book/reference/ldap-sect-user-group-mapping.html">map LDAP groups to Nexus Roles<sup><img src="https://docs.sonatype.com/images/icons/linkext7.gif" border="0" alt="" width="7" height="7" align="absmiddle" /></sup></a></li>
    <li>Ability to <a rel="nofollow" href="http://www.sonatype.com/books/nexus-book/reference/ldap-sect-mapping-roles-ldap.html">assign an LDAP user a specific role<sup><img src="https://docs.sonatype.com/images/icons/linkext7.gif" border="0" alt="" width="7" height="7" align="absmiddle" /></sup></a></li>
    <li>Support for common security models used in Active Directory and LDAP.</li>
    <li>Support for Static and Dynamic Groups</li>
</ul>

<p><strong>Authentication</strong></p>

<p>The Nexus LDAP Authentication Realm which will be available in the Open Source LDAP plugin supports a number of integration patterns for authentication including:</p>

<ul>
    <li><strong>Authentication via a bind</strong>: Delegates authentication to the LDAP server</li>
    <li><strong>SASL Authentication</strong>: Delegates a SASL authentaction to the LDAP server</li>
    <li><strong>Password Attribute</strong>: Nexus checks an encrypted field in the user records.</li>
</ul>

<p><strong>Role Mapping</strong></p>

<p>Nexus Open Source can now be configured to <a rel="nofollow" href="http://www.sonatype.com/books/nexus-book/reference/ldap-sect-user-group-mapping.html">map LDAP groups to Nexus roles<sup><img src="https://docs.sonatype.com/images/icons/linkext7.gif" border="0" alt="" width="7" height="7" align="absmiddle" /></sup></a> . Setting up Nexus to use LDAP groups means you only need to make changes in one location. The next time a user logs in, changes a password, or assigns roles Nexus will automatically synchronize with the LDAP server and these changes will automatically take effect the next time the user logs into the Nexus server. It is also possible to grant users Nexus specific roles, or only use LDAP for authentication and leave the authorization to Nexus.   Brian Fox discussed three approaches to user management in a previous blog post: <a rel="nofollow" href="http://www.sonatype.com/people/2010/01/three-approaches-to-user-management-in-nexus/">Three Approaches to User Management in Nexus<sup><img src="https://docs.sonatype.com/images/icons/linkext7.gif" border="0" alt="" width="7" height="7" align="absmiddle" /></sup></a> .</p>

<p><strong>Support for Multiple Security Models for User and Group Mapping</strong>
Nexus supports all of the common security models used in LDAP servers.   This includes data models used in products like Microsoft&#8217;s Active Directory and standards-driven approaches such as posix.  We&#8217;ve had a lot of positive customer feedback about the intuitive configuration interface which lets you test the role and user mapping from the Nexus administrative interface    If you need to make a change to a group or role mapping, you can test it immediately in the context of Nexus to see if users and groups are being retrieved from your LDAP, Active Directory, or Crowd server.</p>

<p><strong>Support for Static and Dynamic Groups</strong>
Users and groups can be mapped one of two ways in LDAP. Dynamic groups are defined by the user object, whereas static groups are defined by the group. The trade off is speed to ease of management. For dynamic groups one simple query is need to get the user information and which groups that user belongs to, as it is all in one object. With static groups two queries are needed, one to get the user information, and another to check which groups the users is part of. Some LDAP setups user one or the other, some have both where the information is synchronized using triggers.</p>

<p><strong>Stay Tuned</strong></p>

<p>So where&#8217;s the plugin?   How can you install it?  Stay tuned, the Nexus 1.5.0 release will be available this Wednesday afternoon.   Once that release is completed, we will post detailed instructions for people interested in installing Nexus 1.5.0 or upgrading from a prior Nexus installation.</p>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2010/01/nexus-1-5-0-highlights-open-sourcing-nexus-ldap-integration/&via=SonatypeCM&text=Nexus 1.5.0 Highlights: Open Sourcing Nexus LDAP Integration&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2010/01/nexus-1-5-0-highlights-open-sourcing-nexus-ldap-integration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Meet the Nexus Remote Repository Browsing Plugin</title>
		<link>http://www.sonatype.com/people/2010/01/meet-the-nexus-remote-repository-browsing-plugin/</link>
		<comments>http://www.sonatype.com/people/2010/01/meet-the-nexus-remote-repository-browsing-plugin/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 05:10:22 +0000</pubDate>
		<dc:creator>Anders Hammar</dc:creator>
				<category><![CDATA[Nexus]]></category>
		<category><![CDATA[Sonatype]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=4084</guid>
		<description><![CDATA[Having used Nexus since it was a beta release and having also written a Plexus component-style Nexus plugin (the nexus-ldap realm), I was curious about the new Nexus Plugin API introduced in Nexus 1.4.0. To try it out, I asked two of our developers here at Devoteam Sweden to develop the Nexus Remote Repository Browsing [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sonatype.com/people/wp-content/uploads/2010/01/nexus-small.png"><img class="alignright size-full wp-image-3683" title="nexus-small" src="http://www.sonatype.com/people/wp-content/uploads/2010/01/nexus-small.png" alt="" width="250" height="62" /></a>Having used Nexus since it was a beta release and having also written a Plexus component-style Nexus plugin (the nexus-ldap realm), I was curious about the new Nexus Plugin API introduced in Nexus 1.4.0. To try it out, I asked two of our developers here at <a href="http://www.devoteam.se/">Devoteam Sweden</a> to develop the Nexus Remote Repository Browsing Plugin &#8211; a Nexus plugin that makes it possible to directly browse the remote Maven repository of a proxy repository within the Nexus UI. The plugin has been contributed to Nexus OSS and will be released as a part of the upcoming 1.5.0 release.  In this blog post, I will talk a little bit about the plugin and its use case.<span id="more-4084"></span></p>

<p>In the Repository panel of Nexus, there are two tabs for browsing artifacts. The first one is called “Browse Storage” and is used to browse all artifacts stored/cached locally by the Nexus instance. For a hosted repository, the tree displayed under &#8220;Browse Storage&#8221; will contain all available artifacts. For a proxy repository, you will only find those artifacts that have been cached due to earlier requests. The second tab, “Browse Index”, allows you to browse artifacts through the repository’s index.  If the remote repository provides an up-to-date index and you have configured Nexus to download this remote index, all of the artifacts in the remote repository will be visible under the &#8220;Browse Index&#8221; tab.   While the &#8220;Browse Index&#8221; tab works for all of the major public Maven repositories, it doesn&#8217;t allow you to browse remote repositories which do not publish a Nexus index.</p>

<p>This is where the Nexus Remote Repository Browsing Plugin (nexus-rrb-plugin) comes into play. The plugin adds a third browsing tab for proxy repositories, the “Browse Remote” tab. In this tab, it is possible to browse the actual remote repository from within the Nexus UI. Below you find a screen shot of the new tab.</p>

<p><a href="http://www.sonatype.com/people/wp-content/uploads/2010/01/rrb-plugin1.png"><img class="aligncenter size-full wp-image-4091" title="rrb-plugin" src="http://www.sonatype.com/people/wp-content/uploads/2010/01/rrb-plugin1.png" alt="" width="622" height="461" /></a></p>

<p>Before this plugin, the user was forced to browse the remote repository in a separate browser window. Not only is this inconvenient, but for many users it is not possible as the URL of the remote repository is normally only visible to administrators. Also, the connection to the remote repository will be initiated from the Nexus instance. The benefit of this is that it will work even if your network setup prevents direct access from the clients to the remote repository.</p>

<p>This first version of the plugin doesn&#8217;t add any bells and whistles to the browsing. The tab is added to all proxy repositories and is available to all users. However, it does support browsing of Maven repositories at S3, such as the SpringSource repository.  This ability to browse a repository hosted on S3 is significant as it is tricky to do this via a normal web browser.</p>

<p>As mentioned above, the nexus-rrb-plugin is included as a core plugin in the upcoming Nexus 1.5.0 release.   This means that it will be available as a part of the core Nexus OSS offering.   Once Nexus 1.5.0 is released, please try it out and use the <a href="https://issues.sonatype.org/browse/NEXUS">issue tracker</a> for reporting any problems you run into and enhancements you would like to see &#8211; we’re especially interested in hearing about repositories that the plugin cannot handle! Questions and discussions may be posted to the <a href="http://nexus.sonatype.org/project-information.html">Nexus mailing list</a>.</p>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2010/01/meet-the-nexus-remote-repository-browsing-plugin/&via=SonatypeCM&text=Meet the Nexus Remote Repository Browsing Plugin&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2010/01/meet-the-nexus-remote-repository-browsing-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing a Nexus Plugin Using m2eclipse</title>
		<link>http://www.sonatype.com/people/2010/01/writing-a-nexus-plugin-using-m2eclipse/</link>
		<comments>http://www.sonatype.com/people/2010/01/writing-a-nexus-plugin-using-m2eclipse/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 15:44:36 +0000</pubDate>
		<dc:creator>Damian Bradicich</dc:creator>
				<category><![CDATA[m2eclipse]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=3745</guid>
		<description><![CDATA[In this post, I&#8217;m going to walk you through the process of creating a new Nexus plugin using the m2eclipse plugin for eclipse from start to finish including all steps in the process.  After reading this post you will know about the easiest way to get started working on your own Nexus plugin. Some things [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.sonatype.com/people/wp-content/uploads/2010/01/nexus-small.png" alt="nexus-small" title="nexus-small" width="250" height="62" class="alignright size-full wp-image-3683" /></p>

<p>In this post, I&#8217;m going to walk you through the process of creating a new <a href="http://nexus.sonatype.org">Nexus plugin</a> using the <a href="http://m2eclipse.sonatype.org">m2eclipse plugin</a> for eclipse from start to finish including all steps in the process.  After reading this post you will know about the easiest way to get started working on your own Nexus plugin.</p>

<p>Some things to note are that I am using the latest m2e 0.9.9 dev build available from the http://m2eclipse.sonatype.org/update-dev update site.  I am also using eclipse 3.5.1.  All maven builds have been done using local build of latest maven 3.0-SNAPSHOT, however, that is not a requirement for the plugins to work, just a recommendation as maven 3 (in my opinion) is much better than maven 2 <img src='http://www.sonatype.com/people/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

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

<h3>Configuring Your Environment for the Nexus Plugin Project</h3>

<p>To successfully create a Nexus Plugin using the Nexus Plugin archetype, you will need to configure your Maven Settings to include both the Sonatype Forge repository and the Central Maven repository.   If you are already using Nexus and you have configured your settings.xml to use a single, consolidated repository group, all you need to do is add a proxy repository for the Sonatype Forge repository to your repository group.   If you are not using Nexus, you will need to use a settings.xml that resembles the following sample:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;settings<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;profiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;profile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>sonatype-forge<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;repositories<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;repository<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>sonatype-forge<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://repository.sonatype.org/content/groups/forge/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;releases<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/releases<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;snapshots<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/snapshots<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/repository<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/repositories<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pluginRepositories<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pluginRepository<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>sonatype-forge<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://repository.sonatype.org/content/groups/forge/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;releases<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/releases<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;snapshots<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/snapshots<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pluginRepository<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pluginRepositories<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/profile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/profiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;activeProfiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;activeProfile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>sonatype-forge<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/activeProfile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/activeProfiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/settings<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<h3>Creating a New Project with the Nexus Plugin Archetype</h3>

<p>Let&#8217;s start by creating a &#8216;New Maven Project&#8217; in m2eclipse.</p>

<p><img src="http://www.sonatype.com/people/wp-content/uploads/2010/01/new-project.png" alt="new-project" title="new-project" width="523" height="498" class="aligncenter size-full wp-image-3747" /></p>

<p>Select Maven > Maven Project, and click on Next until you reach the archetype selection.  On this screen you can search for and select the archetype which will create your new project. Note that you must use the 1.2 version of the nexus-plugin-archetype.</p>

<p><img src="http://www.sonatype.com/people/wp-content/uploads/2010/01/archetype-selection.png" alt="archetype-selection" title="archetype-selection" width="615" class="aligncenter size-full wp-image-3748" /></p>

<p>Enter the GAV (groupId, artifactId, version) params that will uniquely define the plugin, and click on Next.</p>

<h3>Targeting the Proper Nexus Version</h3>

<p>After supplying the project identifiers, you will see a panel that display the archetype property ${nexusVersion}.  This is the version of Nexus that your plugin will target and it will associate your project with the proper set of dependencies for a specific version of Nexus.</p>

<p><img src="http://www.sonatype.com/people/wp-content/uploads/2010/01/gav-params.png" alt="gav-params" title="gav-params" width="671" height="541" class="aligncenter size-full wp-image-3749" /></p>

<p>By default the nexus-plugin-archetype will target Nexus version 1.4.1.   If you are targeting 1.4.1, it is important that you add the following to your project&#8217;s dependency management because of a problem w/ the parent POM of Nexus 1.4.1.   <b>If you are not tied to using Nexus 1.4.1 we strongly recommend that you update the Nexus version you are targeting 1.4.2-SNAPSHOT and disregard this change.</b>   The 1.4.2-SNAPSHOT POMs have been updated properly and they do not require the following dependency management workaround.</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencyManagement<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;">&lt;!- Workaround for swizzle-jira:1.3.3-SONATYPE-2, as it has an incorrect parent -<span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.swizzle<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>swizzle-jira<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.3.3-SONATYPE-221<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencyManagement<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>If you have already generated the project, and you need to change the target Nexus version you will need to edit this new project&#8217;s POM. Open up the POM of your Nexus Plugin and find the section that defines properties. You will need to change the nexus-version property to target a Nexus version. After creating a project with the Nexus Plugin archetype, you will see a properties section of the POM that contains a ${nexusVersion} reference as follows:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;project<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  ...
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #808080; font-style: italic;">&lt;!-- Set the Nexus version here, against which you build the plugin --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nexus-version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${nexusVersion}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nexus-version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  ...
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/project<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>Click Next after setting the ${nexusVersion}, and voila, we have a nexus-plugin project.</p>

<h3>Building and Deploying the Plugin Project</h3>

<p>Your new Nexus plugin project has some sample components you can use as a starting point for your own plugin development.</p>

<p><img src="http://www.sonatype.com/people/wp-content/uploads/2010/01/new-project-package-explorer.png" alt="new-project-package-explorer" title="new-project-package-explorer" width="367" height="364" class="aligncenter size-full wp-image-3753" /></p>

<p>You can now build this project and expand the bundle right into your nexus installation ${nexus-work-dir}/plugin-repository/</p>

<p><img src="http://www.sonatype.com/people/wp-content/uploads/2010/01/nexus-work-directory-layout.png" alt="nexus-work-directory-layout" title="nexus-work-directory-layout" width="306" height="120" class="aligncenter size-full wp-image-3754" /></p>

<p>And when Nexus starts it will find the plugin and load it automatically.    For this sample plugin, you should see the log message in the Nexus log:</p>

<blockquote><p>Plugin manager &#8220;ACTIVATE&#8221; on plugin &#8220;org.sonatype.nexus.plugin:test-plugin:0.0.1-SNAPSHOT&#8221; was successful.</p></blockquote>

<p>As expected, you are now able to properly use the new plexus resource, I used curl to perform a GET against the default /sample/hello service added to my Nexus instance.  The best part is that we have achieved everything you see above with absolutely zero code, Maven Archetypes really do simplify things for you <img src='http://www.sonatype.com/people/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p><img src="http://www.sonatype.com/people/wp-content/uploads/2010/01/curl-example.png" alt="curl-example" title="curl-example" width="527" height="44" class="aligncenter size-full wp-image-3755" /></p>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2010/01/writing-a-nexus-plugin-using-m2eclipse/&via=SonatypeCM&text=Writing a Nexus Plugin Using m2eclipse&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2010/01/writing-a-nexus-plugin-using-m2eclipse/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>How to make an executable jar in Maven</title>
		<link>http://www.sonatype.com/people/2009/08/how-to-make-an-executable-jar-in-maven/</link>
		<comments>http://www.sonatype.com/people/2009/08/how-to-make-an-executable-jar-in-maven/#comments</comments>
		<pubDate>Thu, 13 Aug 2009 17:13:18 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[Sonatype]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=2696</guid>
		<description><![CDATA[It&#8217;s been a while since I posted, so here&#8217;s a quick and dirty code by example: If you want to make a standalone jar (ie one with no dependencies) executable, here&#8217;s how you do it: &#60;pluginManagement&#62; &#60;plugins&#62; &#60;plugin&#62; &#60;groupId&#62;org.apache.maven.plugins&#60;/groupId&#62; &#60;artifactId&#62;maven-jar-plugin&#60;/artifactId&#62; &#60;configuration&#62; &#60;archive&#62; &#60;manifest&#62; &#60;addClasspath&#62;true&#60;/addClasspath&#62; &#60;mainClass&#62;com.yourcompany.YourClass&#60;/mainClass&#62; &#60;/manifest&#62; &#60;/archive&#62; &#60;/configuration&#62; &#60;/plugin&#62; &#60;/plugins&#62; &#60;/pluginManagement&#62; If however you have [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I posted, so here&#8217;s a quick and dirty code by example:</p>

<p>If you want to make a standalone jar (ie one with no dependencies) executable, here&#8217;s how you do it:
<span id="more-2696"></span></p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pluginManagement<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-jar-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;archive<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;manifest<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
              <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;addClasspath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/addClasspath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
              <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mainClass<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.yourcompany.YourClass<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mainClass<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/manifest<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/archive<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pluginManagement<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>If however you have dependencies, you will probably want to bundle them into a single jar, otherwise making it executable is not very helpful. You can use the assembly plugin to do it like this:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-assembly-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
           <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>attached<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>package<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
           <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;descriptorRefs<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
             <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;descriptorRef<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jar-with-dependencies<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/descriptorRef<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/descriptorRefs<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;archive<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;manifest<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
              <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mainClass<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.yourcompany.YourClass<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mainClass<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/manifest<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/archive<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
     <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>A few comments:</p>

<ol>
    <li>I didn&#8217;t specify plugin versions in the example. You should always specify a plugin version, but you should do it in the pluginManagement section instead. See this <a href="http://www.sonatype.com/people/2008/04/maven-209-released/">post</a> for how and why. </li>
    <li>Notice the assembly plugin configuration has an execution, while the jar plugin does not. This is because the jar plugin will run automatically based on the packaging, which is assumed to be &#8220;jar&#8221; in this example. The assembly plugin needs an execution to &#8220;bind&#8221; it to the lifecycle and here we tell it which goal to run and which phase to run in.</li>
    <li>Notice also that the jar plugin is configured in pluginManagement. This is my personal best practice and I explain why <a href="http://www.sonatype.com/people/2008/05/optimal-maven-plugin-configuration/">here</a>.</li>
</ol>

<p>See more Maven How-Tos and Best Practices <a href="http://www.sonatype.com/people/2009/04/summary-of-maven-how-tos/">here</a>.</p>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2009/08/how-to-make-an-executable-jar-in-maven/&via=SonatypeCM&text=How to make an executable jar in Maven&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2009/08/how-to-make-an-executable-jar-in-maven/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing Plugins for Nexus (Part 1)</title>
		<link>http://www.sonatype.com/people/2009/06/writing-plugins-for-nexus-part-1/</link>
		<comments>http://www.sonatype.com/people/2009/06/writing-plugins-for-nexus-part-1/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 10:00:44 +0000</pubDate>
		<dc:creator>Tamas Cservenak</dc:creator>
				<category><![CDATA[Nexus]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=2336</guid>
		<description><![CDATA[Nexus is a Plexus application, it uses Plexus as a container. As we are well aware, Plexus isn&#8217;t the only Depedency Injection framework currently available. We decided to design the Nexus plugin mechanism to allow for extensibility in a container independent way. If you want to write a plugin for Nexus (and possibly all other [...]]]></description>
			<content:encoded><![CDATA[<p>Nexus is a Plexus application, it uses Plexus as a container.    As we are well aware, Plexus isn&#8217;t the only Depedency Injection framework currently available.   We decided to design the Nexus plugin mechanism to allow for extensibility in a container independent way.   If you want to write a plugin for Nexus (and possibly all other Sonatype products) you don&#8217;t need to pick up a book on Plexus, we&#8217;re trying to make it easier for someone to innovate on the Nexus platform without having to adopt a whole series of technologies.</p>

<p>This post covers some of the initial steps, that are required to write a plugin for Nexus.  Although Nexus is a Plexus application, we want to give 3rd party developers ability to extend Nexus, without forcing them to know Plexus.   We also want to give 3rd party developers the ability to extend Nexus, without burying themselves into Nexus internals.   Clearly if someone wants to add complex, highly custom behavior to Nexus they will need to dive into the internals, but it should be easy to add a simple extension to Nexus without having a PhD in Nexus Internals.    We are also committed to adopting 3rd party &#8220;specs/suggestions/APIs&#8221; that look promising, even if it comes from another IoC provider.</p>

<p>Now, let&#8217;s replace the &#8220;Nexus&#8221; in above sentences with &#8220;Sonatype Application&#8221; in the sentences above. It&#8217;s not so different, right?  At Sonatype, we&#8217;re convinced that providing an intuitive plugin and extension mechanism is critical for adoption and we want to make it as straightforward as possible.  To start this discussion, we need first a look at how Plexus works.</p>

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

<h3>Plexus in 3 minutes</h3>

<p>Plexus &#8220;managed beans&#8221; are called &#8220;components&#8221;.  In contrast to the way most people use Spring, where each bean has a unique name or &#8220;ID&#8221;, Plexus components are addressed with <strong>two</strong> coordinates: <em>role</em> and <em>hint</em>.</p>

<p>Plexus encourages the use of interfaces when defining components. Generally spoken, when implementing one component in Plexus, you will almost always end up with two compilation units: a Java interface, that sets the contract that your component fulfills, and an implementation (or multiple implementations) that implements the contract interface. Again, this is not enforced at all, but is considered as &#8220;best practice&#8221;.</p>

<p>While these two coordinates are internally represented as plain strings, the role is usually a FQN of the interface that component &#8220;provides&#8221; (or implements).   For example, the role might be something like &#8220;com.sonatype.component.TestComponent&#8221; which is the FQN of an interface used to define the contract of the component.   This is not enforced at all in Plexus and it&#8217;s tooling (for example, the plexus-component-metadata Maven plugin), but again, is considered a &#8220;best practice&#8221;. The &#8220;hint&#8221; is actually a free string qualifier, to be able to differentiate amongst multiple implementors (components) with same role, if needed. There is one special hint used internally by Plexus: &#8220;default&#8221;, which is used when no hint is supplied.</p>

<p>Why is this important? Well, usually you have two major situations with your components (managed beans). For one component contract interface you either have:</p>

<ul>
<li>one &#8220;default&#8221; implementation across your application (singular case),</li>
<li>or you may have multiple different implementations of same component contract (plural case)</li>
</ul>

<p>Do not confuse the singular case with &#8220;singleton&#8221; pattern: in both cases the components (managed beans) <strong>are singletons</strong>. We are just providing <strong>one or multiple implementations</strong> for same interface. But in both cases, the actual classes being created by container are singletons (unless you say different in your Plexus annotations, but that&#8217;s another story, and I don&#8217;t want to complicate existing examples).</p>

<p>Another case is how the &#8220;consumer&#8221; of that component &#8212; which is probably some other component in your application &#8212; decides which implementation it wants to use. Or maybe it doesn&#8217;t care at all?</p>

<p>The simplest example of &#8220;singular&#8221; case, the component contract interface and it&#8217;s implementation:</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> MyComponent
<span style="color: #009900;">&#123;</span>
  <span style="color: #003399;">String</span> getHello<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: #003399;">Component</span><span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>MyComponent.<span style="color: #000000; font-weight: bold;">class</span> <span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> DefaultMyComponent
  <span style="color: #000000; font-weight: bold;">implements</span> MyComponent
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getHello<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #0000ff;">&quot;hello&quot;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>That&#8217;s all you need. We just created a MyComponent component contract (interface), and provided one implementation. The implementation is even annotated using Plexus annotation, that states &#8220;this class is a component with role MyComponent&#8221;. Since we say nothing about the hint of component, Plexus implicitly manages it as &#8220;default&#8221; implementation (one-and-only).</p>

<p>The consumer of this component does something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@<span style="color: #003399;">Component</span><span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>SomeOtherComponent.<span style="color: #000000; font-weight: bold;">class</span> <span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AComponentConsumer
  <span style="color: #000000; font-weight: bold;">implements</span> SomeOtherComponent
<span style="color: #009900;">&#123;</span>
  @Requirement
  <span style="color: #000000; font-weight: bold;">private</span> MyComponent myComponent<span style="color: #339933;">;</span>
&nbsp;
  ...
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>Here, with @Requirement annotation we declared a &#8220;requirement&#8221; (we need it injected) to the MyComponent interface. The Plexus will try to fulfill this requirement by looking up a component with role MyComponent, and hint &#8220;default&#8221; (implicit hint), since we did not say anything about needed hint.</p>

<p>For the second case (one contract, multiple implementations), the most simpler example is this:</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> Archiver
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">void</span> archive<span style="color: #009900;">&#40;</span> <span style="color: #003399;">File</span> source, <span style="color: #003399;">File</span> archiveFile <span style="color: #009900;">&#41;</span>
      <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">void</span> unarchive<span style="color: #009900;">&#40;</span> <span style="color: #003399;">File</span> archiveFile, <span style="color: #003399;">File</span> destination <span style="color: #009900;">&#41;</span>
      <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>and having component implementations like these:</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@<span style="color: #003399;">Component</span><span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>Archiver.<span style="color: #000000; font-weight: bold;">class</span>, hint<span style="color: #339933;">-</span><span style="color: #0000ff;">&quot;zip&quot;</span> <span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ZipArchiver
  <span style="color: #000000; font-weight: bold;">implements</span> Archiver
<span style="color: #009900;">&#123;</span>
  ...
<span style="color: #009900;">&#125;</span>
&nbsp;
@<span style="color: #003399;">Component</span><span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>Archiver.<span style="color: #000000; font-weight: bold;">class</span>, hint<span style="color: #339933;">-</span><span style="color: #0000ff;">&quot;tgz&quot;</span> <span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TgzArchiver
  <span style="color: #000000; font-weight: bold;">implements</span> Archiver
<span style="color: #009900;">&#123;</span>
  ...
<span style="color: #009900;">&#125;</span>
&nbsp;
@<span style="color: #003399;">Component</span><span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>Archiver.<span style="color: #000000; font-weight: bold;">class</span>, hint<span style="color: #339933;">-</span><span style="color: #0000ff;">&quot;7z&quot;</span> <span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SevenZArchiver
  <span style="color: #000000; font-weight: bold;">implements</span> Archiver
<span style="color: #009900;">&#123;</span>
  ...
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>The consumer of Archiver does something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@<span style="color: #003399;">Component</span><span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>SomeOtherComponent.<span style="color: #000000; font-weight: bold;">class</span> <span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AComponentConsumer
  <span style="color: #000000; font-weight: bold;">implements</span> SomeOtherComponent
<span style="color: #009900;">&#123;</span>
  @Requirement<span style="color: #009900;">&#40;</span> hint<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;zip&quot;</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">private</span> Archiver zipArchiver<span style="color: #339933;">;</span>
&nbsp;
  ...
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>In case above we &#8220;wired&#8221; the AComponentConsumer to support &#8220;zip&#8221; archives only. But we may do something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@<span style="color: #003399;">Component</span><span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>SomeOtherComponent.<span style="color: #000000; font-weight: bold;">class</span> <span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AComponentConsumer
  <span style="color: #000000; font-weight: bold;">implements</span> SomeOtherComponent
<span style="color: #009900;">&#123;</span>
  @Requirement<span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>Archiver.<span style="color: #000000; font-weight: bold;">class</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">List</span> archivers<span style="color: #339933;">;</span>
&nbsp;
  ...
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>or</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@<span style="color: #003399;">Component</span><span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>SomeOtherComponent.<span style="color: #000000; font-weight: bold;">class</span> <span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AComponentConsumer
  <span style="color: #000000; font-weight: bold;">implements</span> SomeOtherComponent
<span style="color: #009900;">&#123;</span>
  @Requirement<span style="color: #009900;">&#40;</span> role<span style="color: #339933;">=</span>Archiver.<span style="color: #000000; font-weight: bold;">class</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Map</span> archivers<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> archive<span style="color: #009900;">&#40;</span> <span style="color: #003399;">File</span> src, <span style="color: #003399;">File</span> dest <span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #003399;">String</span> destExt <span style="color: #339933;">=</span> getFileExtension<span style="color: #009900;">&#40;</span> dest <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> archivers.<span style="color: #006633;">containsKey</span><span style="color: #009900;">&#40;</span> destExt <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      Archiver archiver <span style="color: #339933;">=</span> archivers.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span> destExt <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      archiver.<span style="color: #006633;">archive</span><span style="color: #009900;">&#40;</span> src, dest <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      ...
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">else</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IOException</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;Archive format unsupported!&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>It is obvious, that in this example, Plexus will inject a Map&lt;String, Archiver&gt; into AComponentConsumer, where the String keys will be hints of components in the Map, and values will be Archiver instances with given key.</p>

<h3>So?</h3>

<p>So, why is this important? &#8212; you ask. Well, in Nexus, the &#8220;extension points&#8221; are simply taken, &#8220;marked&#8221; interfaces (roles), that will be automatically pulled by Plexus collection lookups similar to this last example. Marked by Nexus developers, and pointed out as &#8220;extension point&#8221; to the 3rd party plugin developers.</p>

<p>Actually, up to now, this was how Nexus supported &#8220;plugins&#8221;. &#8220;Plugins&#8221; and not plugins, up to now, the job of the developer was to code Plexus components, build them, provide Plexus descriptors for the plugin (usually by annotating the classes as above and using the plexus-component-metadata plugin, which embeds the descriptor into resulting JAR), and &#8220;drop it&#8221; into Nexus lib.</p>

<p>Since the developers implemented and marked their classes as @Component with roles that were looked up, after booting up Nexus with new JAR in it&#8217;s lib folder, Nexus was aware of these and would start using them as if they were a part of the &#8220;core&#8221;. Simple as that.</p>

<p>The downside of this approach is twofold:</p>

<ul>
    <li>3rd party developers are forced to use Plexus, plexus tooling, etc. Also, they must be aware of Nexus internals, for example that Repository components should be **prototypes**, and not **singletons**.</li>
    <li>the plugins are more like &#8220;extensions&#8221;, since they total and uncontrolled access to all of the Nexus internals, not just extension points.</li>
</ul>

<h2>The Idea</h2>

<p>In short:</p>

<ul>
    <li>let the &#8220;host application developers&#8221; mark and parametrize the extension points (@ExtensionPoint)</li>
    <li>let the &#8220;3rd party plugin developers&#8221; create extensions by implementing interfaces marked with @ExtensionPoint.</li>
    <li>provide IoC abilities for &#8220;3rd party pluging developers&#8221;</li>
    <li>let the &#8220;3rd party plugin developers&#8221; create their own managed beans, components with all the IoC benefits</li>
    <li>load the plugin in separate classloader</li>
</ul>

<p>Okay, let&#8217;s draft the idea: having &#8220;extension points&#8221;, which are all simple Java interfaces (component contracts) and are provided by &#8220;host application&#8221; developers (in this case Nexus developers). This is simple to understand: the <strong>host application developers</strong> are the one who know the what, where, and how about what is extensible within the application. Thus, we need to provide some means for developers, to mark their interfaces as @ExtensionPoint. Almost always, the case with components here is the &#8220;plural&#8221; case (one component interface, with multiple implementations, 3rd party developers just adding new ones to the pool of existing). But again, usually the host application developers are the ones who knos, and should provide information on extension points about instantiation details of the component implementations (singletons versus prototypes for example).</p>

<p>When the host application API has decorated interfaces (API), the <strong>3rd party plugin developers</strong> may kick in, by implementing @ExtensionPoints. All they have to do is pick a component interface marked as @ExtensionPoint, and implement it. That&#8217;s all. And what about IoC?</p>

<p>We decided to accept the @Inject project proposal at code.google.com, and use &#8220;meta-metadata&#8221; to decorate the components. Since @Inject already proposes a meta-metadata to make possible to annotate classes and use them across Guice and Spring, we thought making it work with Plexus would be nice too.</p>

<p>Thus, in short, 3rd party Nexus plugin developers should use @Inject annotations only. Naturally, when deployed to Nexus, their components will be &#8220;powered by Plexus&#8221; under the hud, but it&#8217;s not their problem and they should not care about it.</p>

<p>The Nexus Plugin Manager will have another great feature: <strong>class loader separation</strong>. Right now, since as I said, the plugin JAR was just dropped into Nexus lib folder, that implicitly means that plugins were doomed to use the same versions of dependencies that were already present in Nexus (newly introduced dependencies are fine, though). This led to the proliferation and over user of the Maven Shade plugin. Don&#8217;t get me wrong, I think this plugin is very-very useful, but it must be used with care (not to mention it&#8217;s flaw, that it &#8220;shades&#8221; stuff always under hidden package, instead to somewhere module specific place. Two jars with same shaded dependency may again clash).</p>

<p>One more thing: the @Inject proposal does not mention how to create new managed beans, they have no means to annotate a new component (well, in case of Guice it happens implicitly with @Inject, making the interface needed in binding).  This is where another new annotation comes in: @Managed. The @Managed annotation will be used on Java <strong>interfaces only</strong>, to mark them as component contracts.</p>

<p>So, in short:</p>

<ul>
    <li>Host application developers should point out the &#8220;extension point&#8221; interfaces in the apps. Also, they should provide as much &#8220;metadata&#8221; as possible about the instances of those components.</li>
    <li>plugin developers should only care about implementing those marked interfaces, and not fiddle with annotating them with some container-specific stuff</li>
    <li>use @Inject project annotations</li>
    <li>add ability to plugin developers to enjoy the benefits of IoC containers, and let them defined their own components (again, no Plexus needed).</li>
</ul>

<h2>Teaser</h2>

<p>Here is an example of a theoretical implementation of artifact virus scanner for Nexus. In short: we want to make sure no virus infected artifact will come in our Nexus instance. Internal deployments are considered &#8220;safe&#8221;, thus proxy requests are checked only.</p>

<p>These is what we need to implement this plugin:</p>

<ul>
    <li>A Virus scanner implementation (not shown here for example&#8217;s brevity&#8217;s sake)</li>
    <li>A Nexus RequestProcessor (extension point) implementation. RequstProcessor components are able to interact with every Nexus request, and stop their execution at different stages</li>
    <li>A Nexus RepositoryCustomizer (extension point) implementation, to inject the RequestProcessor from above to repositories we want</li>
</ul>

<p>We start with creating a managed component contract for Virus Scanner:</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">org.sample.plugin</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.InputStream</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.plugins.Managed</span><span style="color: #339933;">;</span>
&nbsp;
@Managed
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> VirusScanner
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">boolean</span> hasVirus<span style="color: #009900;">&#40;</span> <span style="color: #003399;">InputStream</span> is <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>Then we implement it. This is a &#8220;singular&#8221; case, the newly introduced component contract interface has only one default implementation:</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">org.sample.plugin</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.InputStream</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.inject.Named</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> XYVirusScanner
    <span style="color: #000000; font-weight: bold;">implements</span> VirusScanner
<span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> hasVirus<span style="color: #009900;">&#40;</span> <span style="color: #003399;">InputStream</span> is <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// DO THE JOB HERE</span>
        <span style="color: #000000; font-weight: bold;">return</span> resultOfTheScanning<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>Next, a RequestProcessor. It requires VirusScanner to do the work.   We are not making a decision until we  get to the content in shouldCache(). We are using the @Inject annotations to inject our newly created component.  Since VirusScannerRequestProcessor implements a Nexus extension point (they are &#8220;plural&#8221; components), we need to reference it later (see below in VirusScannerRepositoryCustomizer), we are &#8220;naming it&#8221; with the @Named annotation.</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">org.sample.plugin</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.inject.Inject</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.inject.Named</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.ResourceStoreRequest</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.access.Action</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.item.AbstractStorageItem</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.item.StorageFileItem</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.repository.ProxyRepository</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.repository.Repository</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.repository.RequestProcessor</span><span style="color: #339933;">;</span>
&nbsp;
@Named<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;virusScanner&quot;</span> <span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> VirusScannerRequestProcessor
    <span style="color: #000000; font-weight: bold;">implements</span> RequestProcessor
<span style="color: #009900;">&#123;</span>
    @Inject
    <span style="color: #000000; font-weight: bold;">private</span> VirusScanner virusScanner<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> process<span style="color: #009900;">&#40;</span> <span style="color: #003399;">Repository</span> repository, ResourceStoreRequest request, <span style="color: #003399;">Action</span> action <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// don't decide until have content</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> shouldProxy<span style="color: #009900;">&#40;</span> ProxyRepository repository, ResourceStoreRequest request <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// don't decide until have content</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> shouldCache<span style="color: #009900;">&#40;</span> ProxyRepository repository, AbstractStorageItem item <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> item <span style="color: #000000; font-weight: bold;">instanceof</span> StorageFileItem <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            StorageFileItem file <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>StorageFileItem<span style="color: #009900;">&#41;</span> item<span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// do a virus scan</span>
            <span style="color: #000000; font-weight: bold;">try</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">return</span> virusScanner.<span style="color: #006633;">hasVirus</span><span style="color: #009900;">&#40;</span> file.<span style="color: #006633;">getInputStream</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>
            <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span> <span style="color: #003399;">IOException</span> e <span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #666666; font-style: italic;">// handle it</span>
                <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>Finally, we are creating a RepositoryCustomizer (also a &#8220;plural&#8221; component, but we don&#8217;t care about naming it), that will inject our RequestProcessor into repository instances we need. In this case, those are proxy repositories (the only ones able to fetch artifacts from remote repositories).</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">org.sample.plugin</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.inject.Inject</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.inject.Named</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.configuration.ConfigurationException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.plugins.RepositoryCustomizer</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.repository.ProxyRepository</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.repository.Repository</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.sonatype.nexus.proxy.repository.RequestProcessor</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> VirusScannerRepositoryCustomizer
    <span style="color: #000000; font-weight: bold;">implements</span> RepositoryCustomizer
<span style="color: #009900;">&#123;</span>
    @Inject
    <span style="color: #000000; font-weight: bold;">private</span> @Named<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;virusScanner&quot;</span> <span style="color: #009900;">&#41;</span>
    RequestProcessor virusScannerRequestProcessor<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> isHandledRepository<span style="color: #009900;">&#40;</span> <span style="color: #003399;">Repository</span> repository <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// handle proxy reposes only</span>
        <span style="color: #000000; font-weight: bold;">return</span> repository.<span style="color: #006633;">getRepositoryKind</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">isFacetAvailable</span><span style="color: #009900;">&#40;</span> ProxyRepository.<span style="color: #000000; font-weight: bold;">class</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;">public</span> <span style="color: #000066; font-weight: bold;">void</span> configureRepository<span style="color: #009900;">&#40;</span> <span style="color: #003399;">Repository</span> repository <span style="color: #009900;">&#41;</span>
        <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">ConfigurationException</span>
    <span style="color: #009900;">&#123;</span>
        repository.<span style="color: #006633;">getRequestProcessors</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;virusScanner&quot;</span>, virusScannerRequestProcessor <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>That&#8217;s all for now. In the next part, we will make more in-depth explanations of the plugin API, and explain what is happening &#8220;behind the curtains&#8221;.  Have fun!</p>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2009/06/writing-plugins-for-nexus-part-1/&via=SonatypeCM&text=Writing Plugins for Nexus (Part 1)&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2009/06/writing-plugins-for-nexus-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to make a plugin that runs once during a build</title>
		<link>http://www.sonatype.com/people/2009/05/how-to-make-a-plugin-run-once-during-a-build/</link>
		<comments>http://www.sonatype.com/people/2009/05/how-to-make-a-plugin-run-once-during-a-build/#comments</comments>
		<pubDate>Fri, 22 May 2009 11:36:05 +0000</pubDate>
		<dc:creator>Brian Fox</dc:creator>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=2270</guid>
		<description><![CDATA[With it's default behavior, Maven runs a plugin invocation for each project in a multi-module build. For plugins that operate on a single project at a time, this is what the author wants.

Some plugins are what we call "aggregators" which means they actually do want all the information about the full multi-module build before execution. These plugins, when run on a tree of projects cause Maven to resolve all the children before calling the plugin's execute() method. In this mode a plugin executes just once, but effectively on the whole tree at once. (<em>as a side note, you never want to bind an aggregator goal in your pom as this would cause the plugin to run an n! recursive build since the lifecycle would step into each child and execute the aggregator...which would cause Maven to reresolve all the children, etc</em>)

Sometimes neither of those behaviors are what you want.]]></description>
			<content:encoded><![CDATA[<p>With it&#8217;s default behavior, Maven runs a plugin invocation for each project in a multi-module build. For plugins that operate on a single project at a time, this is what the author wants.</p>

<p>Some plugins are what we call &#8220;aggregators&#8221; which means they actually do want all the information about the full multi-module build before execution. These plugins, when run on a tree of projects cause Maven to resolve all the children before calling the plugin&#8217;s execute() method. In this mode a plugin executes just once, but effectively on the whole tree at once. (<em>as a side note, you never want to bind an aggregator goal in your pom as this would cause the plugin to run an n! recursive build since the lifecycle would step into each child and execute the aggregator&#8230;which would cause Maven to reresolve all the children, etc</em>)</p>

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

<p>Sometimes neither of those behaviors are what you want. If I want a plugin to run only once in my build, I can do that by only binding it once in a pom. But what if you want it to run once regardless of if I start my build at the root, or somewhere down in a module? An example of where this is handy is the <a href="http://maven.apache.org/plugins/maven-enforcer-plugin/">maven-enforcer-plugin</a>&#8230; if you&#8217;re checking environmental constraints like jdk, os, maven version, it&#8217;s pretty much guaranteed that this can&#8217;t change between the root and when the next module is built.</p>

<p>This has most recently cropped up as a use case in the <a href="http://maven.apache.org/plugins/maven-assembly-plugin/">maven-assembly-plugin</a>. We want to configure the plugin to produce a source archive during releases of the entire tree. Since the root project would contain the code below that point, we don&#8217;t need to also archive the source for each sub-module separately. We want to be able to configure this at our &#8220;Maven&#8221; or &#8220;Apache&#8221; pom (the moral equivalent of a &#8220;<a href="http://www.sonatype.com/people/2008/05/misused-maven-terms-defined/">Corporate</a>&#8221; pom) and have it simply work regardless of where a build is launched from.</p>

<p>It turns out that it is fairly easy for a plugin to programatically detect when it is building the project at the execution root (that is where mvn was launched). The code looks like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>57
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">        <span style="color: #000066; font-weight: bold;">boolean</span> result <span style="color: #339933;">=</span> mavenSession.<span style="color: #006633;">getExecutionRootDirectory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">equalsIgnoreCase</span><span style="color: #009900;">&#40;</span>basedir.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>


<p>A full mojo to implement this would look like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #008000; font-style: italic; font-weight: bold;">/**
* @goal skipper
* @execute phase=&quot;validate&quot;
**/</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SkipperMojo <span style="color: #000000; font-weight: bold;">extends</span> AbstractMojo
<span style="color: #009900;">&#123;</span>
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Base directory of the project.
     *
     * @parameter default-value=&quot;${basedir}&quot;
     * @required
     * @readonly
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">File</span> basedir<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * This will cause the assembly to run only at the top of a given module tree. That is, run in the project
     * contained in the same folder where the mvn execution was launched.
     * @parameter expression=&quot;${runOnlyAtExecutionRoot}&quot; default-value=&quot;false&quot;
     * @since 2.2-beta-4
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">boolean</span> runOnlyAtExecutionRoot<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000000; font-weight: bold;">throws</span> MojoExecutionException, MojoFailureException
    <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">//run only at the execution root.</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>runOnlyAtExecutionRoot <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>isThisTheExecutionRoot<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            getLog<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;Skipping the assembly in this project because it's not the Execution Root&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #009900;">&#123;</span>
            getLog<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Doing something usefull&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
   <span style="color: #009900;">&#125;</span>
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Returns true if the current project is located at the Execution Root Directory (where mvn was launched)
     * @return
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">boolean</span> isThisTheExecutionRoot<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        Log log <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">getLog</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        log.<span style="color: #006633;">debug</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Root Folder:&quot;</span> <span style="color: #339933;">+</span> mavenSession.<span style="color: #006633;">getExecutionRootDirectory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        log.<span style="color: #006633;">debug</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Current Folder:&quot;</span><span style="color: #339933;">+</span> basedir <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">boolean</span> result <span style="color: #339933;">=</span> mavenSession.<span style="color: #006633;">getExecutionRootDirectory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">equalsIgnoreCase</span><span style="color: #009900;">&#40;</span>basedir.<span style="color: #006633;">toString</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: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>result<span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            log.<span style="color: #006633;">debug</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;This is the execution root.&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #009900;">&#123;</span>
            log.<span style="color: #006633;">debug</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;This is NOT the execution root.&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000000; font-weight: bold;">return</span> result<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2009/05/how-to-make-a-plugin-run-once-during-a-build/&via=SonatypeCM&text=How to make a plugin that runs once during a build&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2009/05/how-to-make-a-plugin-run-once-during-a-build/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maven: Integration and Distributed, Open Innovation</title>
		<link>http://www.sonatype.com/people/2009/05/maven-integration-and-distributed-open-innovation/</link>
		<comments>http://www.sonatype.com/people/2009/05/maven-integration-and-distributed-open-innovation/#comments</comments>
		<pubDate>Fri, 08 May 2009 13:08:49 +0000</pubDate>
		<dc:creator>Tim O'Brien</dc:creator>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[OSGi]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[Scala]]></category>

		<guid isPermaLink="false">http://www.sonatype.com/people/?p=2161</guid>
		<description><![CDATA[Brian Murphy wrote a long blog post about the PAX Plugin which provides a good example of the power of Maven to act as an integration &#8220;bridge&#8221; between a number of unrelated technologies. In this post, Brian is using the PAX Maven Plugin from ops4j together with the gmaven-plugin and the maven-scala-plugin, he concludes with [...]]]></description>
			<content:encoded><![CDATA[<p>Brian Murphy wrote a <a href="http://tr.im/kP9w">long blog post about the PAX Plugin</a> which provides a good example of the power of Maven to act as an integration &#8220;bridge&#8221; between a number of unrelated technologies.   In this post, Brian is using the <a href="http://tr.im/kPcB">PAX Maven Plugin</a> from ops4j together with the <a href="http://groovy.codehaus.org/GMaven">gmaven-plugin</a> and the <a href="http://tr.im/kPbE">maven-scala-plugin</a>, he concludes with praise for Maven as an essential time saver:</p>

<blockquote>&#8220;This ended up being a much longer article than I anticipated but we&#8217;ve covered a lot of ground. Maven has worked it&#8217;s dependency voodoo which saved an enormous amount of time downloading jars and messing with classpaths. We&#8217;ve seen how the PAX toolkit from OPS4J makes creating, modifying and provisioning OSGi bundles a breeze. While the actual code examples were pretty trivial, we successfully managed to code up bundles in Java, Scala and Groovy. I think this displays a lot of the power that is offered by OSGi and points to a bright future for enterprise development on the JVM.&#8221;</blockquote>

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

<h3>Project-driven Plugins: Distributed, Open Innovation</h3>

<p>In this case Maven is bridging a number of popular projects that have all created well-documented Maven plugins.    Maven is the essential &#8220;glue&#8221; that allows someone like Brian to take a number of unrelated technologies and use them in ways that the designers of GMaven or the Scala plugin could never have predicted.   As Maven matures and continues to evolve its Plugin API, we&#8217;re starting to see more projects and more systems commit to using it as an enabling &#8220;platform&#8221; for development.  Those projects that have adopted Maven have found it beneficial to host and drive the Maven plugins that relate to their project or technology.  <strong>Better support for Maven increases the adoption of Groovy, Scala, and (in this case) OSGi.</strong></p>

<p>The PAX plugin is maintained and hosted by the Ops4J project, the Scala plugin is hosted and maintained by the Scala community, and the GMaven plugin is hosted and maintained by the Groovy community.  Each community feels strongly enough about providing Maven support for their technology that they have made it a part of their project.   This is important because it suggests an evolving approach to the way Maven plugins are created and supported.   Four years ago, it was unlikely to see a project like Scala or Ops4J creating and hosting a Maven plugin.  While Maven was already ubiquitous, projects still didn&#8217;t see Maven support as a primary concern.  Instead, the plugin development would happen as part of the Maven community or in an ancillary community of Maven plugins known as the Mojo project at Codehaus.</p>

<p>Mojo is an important bridge.  It allows third-party actors to craft support for tools like JBoss and GWT, but it is an aggregate, disjoint community with a single mailing list, perfunctory release votes, and little shared discussion about architecture or planning.   It is a free-for-all.  While Mojo does host some essential plugins it is also a dumping grounds for half-finished, owner-less plugins.   As more projects provide their own Maven support, people should consider moving project from Mojo to the projects that develop the specific technologies in question.   This is the &#8220;distributed&#8221; open innovation that will encourage quality, well-documented plugins.</p>

<h3>Why Companies and Projects Need to &#8220;Own&#8221; Their Maven Support</h3>

<p>We&#8217;ve transitioned into a point where projects need to start hosting and owning the Maven plugins that enable developers to use their software.   Google would have been better off if they had invested a day or two crafting a solid Maven plugin for AppEngine before they announced Java support.   Similarly, they should think about driving the development of the GWT plugin.   If your project&#8217;s artifacts are available through the Central Maven repository, that is a first step, but if your project also publishes an artifact and a really compelling Maven plugin, you&#8217;ve made it trivial and easy for people to adopt your technology.   &#8220;Going to market&#8221; without good Maven support no longer makes sense, and you should know that more and more developers are start with the question &#8220;how does this fit into my Maven build?&#8221;  If your answer is &#8220;shrug, we don&#8217;t use Maven&#8221;, it is very likely that they will seek out other solutions that provide better integration.</p>

<p>If you are a tool vendor or create an open source framework, you should be hosting your own Maven plugin as a part of your project.   If you support an SCM like Perforce or Clearcase, you should make sure that your software provides a solid SCM provider for Maven.  If your company or project develops a server, you should be working with the Maven project to make sure that it integrates with Maven.   To do otherwise is to invite your customers or users to look elsewhere for better integration.    If you let someone else drive your Maven plugin, you are really just delegating an essential support function to the community.   The message you are sending is, &#8220;we don&#8217;t really care that you use Maven, it isn&#8217;t a priority, someone will do the integration work for us&#8221;.   This is true, but when that happens, you lose an opportunity to interact with your users and your customers.</p>

<p>PS: Brian&#8217;s post also inspired me to file <a href="https://issues.sonatype.org/browse/MVNDEF-96">this JIRA issue on the MVNDEF book project</a>.   Our book&#8217;s need code examples that can be more easily copied to the clipboard.</p>
<div style="float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.sonatype.com/people/2009/05/maven-integration-and-distributed-open-innovation/&via=SonatypeCM&text=Maven: Integration and Distributed, Open Innovation&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.sonatype.com/people/2009/05/maven-integration-and-distributed-open-innovation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

