Author: aramirez
Date: Mon Feb  6 17:55:43 2006
New Revision: 375444

URL: http://svn.apache.org/viewcvs?rev=375444&view=rev
Log:
-added intro to optional and excludes dependencies

Added:
    
maven/site/trunk/src/site/apt/guides/introduction/introduction-to-optional-and-excludes-dependencies.apt

Added: 
maven/site/trunk/src/site/apt/guides/introduction/introduction-to-optional-and-excludes-dependencies.apt
URL: 
http://svn.apache.org/viewcvs/maven/site/trunk/src/site/apt/guides/introduction/introduction-to-optional-and-excludes-dependencies.apt?rev=375444&view=auto
==============================================================================
--- 
maven/site/trunk/src/site/apt/guides/introduction/introduction-to-optional-and-excludes-dependencies.apt
 (added)
+++ 
maven/site/trunk/src/site/apt/guides/introduction/introduction-to-optional-and-excludes-dependencies.apt
 Mon Feb  6 17:55:43 2006
@@ -0,0 +1,307 @@
+ ------
+ Optional Dependencies and Dependency Exclusions
+ ------
+ Allan Ramirez
+ ------
+ 23 January 2006
+ ------
+
+~~ Copyright 2001-2005 The Apache Software Foundation.
+~~ 
+~~ Licensed under the Apache License, Version 2.0 (the "License");
+~~ you may not use this file except in compliance with the License.
+~~ You may obtain a copy of the License at
+~~ 
+~~      http://www.apache.org/licenses/LICENSE-2.0
+~~ 
+~~ Unless required by applicable law or agreed to in writing, software
+~~ distributed under the License is distributed on an "AS IS" BASIS,
+~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~~ See the License for the specific language governing permissions and
+~~ limitations under the License.
+
+Introduction
+
+  This section discusses the functionality of optional dependencies and 
+  dependency exclusions. This will help users to understand what are they, 
+  how to use them, how they work and when is the best way to use them. 
+  It also explains why exclusions are made as per dependency basis not in 
+  a POM level.
+
+* Optional Dependencies
+
+  Optional dependencies are used when it's not really possible 
+  (for whatever reason) to split a project up into sub-modules. 
+  The idea is that some of the dependencies are only used for certain features 
+  in the project, and will not be needed if that feature isn't used. Ideally, 
+  such a feature would be split into a sub-module that depended on the core 
+  functionality project...this new subproject would have only non-optional 
+  dependencies, since you'd need them all if you decided to use the 
+  subproject's functionality. 
+
+  However, since the project cannot be split up (again, for whatever reason), 
+  these dependencies are declared optional. If a user wants to use 
+  functionality related to an optional dependency, they will have to redeclare 
+  that optional dependency in their own project. This is not the most clear 
+  way to handle this situation, but then again both optional dependencies and
+  dependency exclusions are stop-gap solutions.
+
+** Why use optional dependencies?
+
+  It's not only important to declare optional dependencies in order to save 
+  space/memory/etc. It's vital to control the list of actual dependencies a 
+  person needs in order to use a project, since these jars may eventually make 
+  it into a WAR, EAR, EJB, etc. Inclusion of the wrong jars may violate a 
+  license agreement, cause classpath issues, etc. 
+
+** How do I use the optional tag?
+
+  A dependency is declared as optional by simply setting the \<optional\> tag 
+  to true in your dependency declaration. See the sample below:
+
++---+
+
+<project>
+  ...
+  <dependencies>
+    <!-- declare the dependency to be set as optional -->
+    <dependency>
+      <groupId>sample.ProjectA</groupId>
+      <artifactId>Project-A</artifactId>
+      <version>1.0</version>
+      <scope>compile</scope>
+      <optional>true</optional> <!-- value will be true or false only -->
+    </dependency>
+  </dependencies>
+</project>
+
++---+
+
+** How do optional dependencies work?
+
++---+
+
+Project-A -> Project-B
+
++---+
+
+  The diagram above says that Project-A depends on Project-B. When A 
+  declares B as an optional dependency in its POM, this relationship remains
+  unchanged. Its just like a normal build where Project-B will be added in its 
+  classpath.
+
++---+
+
+Project-X -> Project-A
+
++---+
+
+  But when another project(Project-X) declares Project-A as a dependency in 
+  its POM, the optional dependency takes effect. You'll notice that 
+  Project-B is not included in the classpath of Project-X; you will 
+  need to declare it directly in your POM in order for B to be included 
+  in X's classpath. 
+
+** Example
+
+  Let us say that there is a project named <X2> that has similar functions 
+  with <Hibernate> which supports many database drivers/dependencies such as 
+  mysql, postgre, oracle etc. All of these dependencies are needed for X2 
+  to build but not for your project, so it is very practical for X2 to 
+  declare these dependencies as optional, so that whenever your project 
+  declares X2 as a direct dependency in your POM, all the drivers supported 
+  by the X2 will not be automatically included to your project's classpath 
+  instead you'll have to declare it directly on what driver/dependency of the 
+  database you are going to use.
+
+* Dependency Exclusions
+
+  Since maven 2.x resolves dependencies transitively, it is possible 
+  for unwanted dependencies to be included in your project's classpath.
+  Projects that you depend on may not have declared their set of dependencies
+  correctly, for example. In order to address this special situtation, 
+  maven 2.x has incorporated the notion of explicit dependency exclusion.
+  Exclusions are set on a specific dependency in your POM, and are targeted
+  at a specific groupId and artifactId. When you build your project, that
+  artifact will not be added to your project's classpath <by way of the
+  dependency in which the exclusion was declared>.
+
+** How to use dependency exclusions
+
+  We add the \<exclusions\> tag under the \<dependency\> section of the pom.
+
++---+
+
+<project>
+  ...
+  <dependencies>
+    <dependency>
+      <groupId>sample.ProjectA</groupId>
+      <artifactId>Project-A</artifactId>
+      <version>1.0</version>
+      <scope>compile</scope>
+      <exclusions>
+        <exclusion>  <!-- declare the exclusion here -->
+          <groupId>sample.ProjectB</groupId>
+          <artifactId>Project-B</artifactId>
+        </exclusion>
+      </exclusions> 
+    </dependency>
+  </dependencies>
+</project>
+
++---+
+
+** How dependency exclusion works and when to use it <<( as a last resort! )>>
+
++---+
+
+Project-A
+   -> Project-B
+        -> Project-D <! -- This dependency should be excluded -->
+             -> Project-E
+             -> Project-F
+   -> Project C
+
++---+
+  
+  The diagram shows that Project-A depends on both Project-B and C. Project-B 
+  depends on Project-D. Project-D depends on both Project-E and F. By default, 
+  Project A's classpath will include:
+
++---+
+B, C, D, E, F
++---+
+
+  What if we dont want project D and its dependencies to be added to 
+  Project A's classpath because we know some of Project-D's dependencies 
+  (maybe Project-E for example) was missing from the repository, and you 
+  don't need/want the functionality in Project-B that depends on Project-D 
+  anyway. In this case, Project-B's developers could provide a dependency on 
+  Project-D that is \<optional\>true\</optional\>, like this:
+
++---+
+<dependency>
+  <groupId>sample.ProjectD</groupId>
+  <artifactId>ProjectD</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <optional>true</optional>
+</dependency>
++---+
+
+  HOWEVER, they didn't. As a last resort, you still have the option to exclude 
it 
+  on your side, in Project-A, like this:
+
++---+
+
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>sample.ProjectA</groupId>
+  <artifactId>Project-A</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+  ...
+  <dependencies>
+    <dependency>
+      <groupId>sample.ProjectB</groupId>
+      <artifactId>Project-B</artifactId>
+      <version>1.0-SNAPSHOT</version>
+      <exclusions>
+        <exclusion>
+         <groupId>sample.ProjectD</groupId> <!-- Exclude Project-D from 
Project-B -->
+         <artifactId>Project-D</artifactId>
+       </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+</project>
+
++---+
+
+  If we deploy the Project-A to a repository, and Project-X declares a 
+  normal dependency on Project-A, will Project-D be excluded from the 
+  classpath still?
+
++---+
+
+Project-X -> Project-A
+
++---+
+
+  The answer is <<Yes>>. Project-A has declared that it doesn't need 
+  Project-D to run, so it won't be brought in as a transitive dependency 
+  of Project-A. 
+
+  Now, consider that Project-X depends on Project-Y, as in the diagram below:
+  
++---+
+
+Project-X -> Project-Y
+               -> Project-B
+                   -> Project-D
+                      ...
+
++---+  
+  
+  Project-Y also has a dependency on Project-B, and it does need the features 
+  supported by Project-D. Therefore, it will NOT place an exclusion on 
+  Project-D in its dependency list. It may also supply an additional 
+  repository, from which we can resolve Project-E. In this case, it's 
important 
+  that Project-D <<is not>> excluded globally, since it is a legitimate 
+  dependency of Project-Y. 
+
+  As another scenario, what if the dependency we don't want is Project-E 
+  instead of Project-D. How will we exclude it? See the diagram below:
+
++---+
+
+Project-A
+   -> Project-B
+        -> Project-D 
+             -> Project-E <!-- Exclude this dependency -->
+             -> Project-F
+   -> Project C
+
++---+  
+
+  Exclusions work on the entire dependency graph below the point where they 
+  are declared. If you wanted to exclude Project-E instead of Project-D, 
+  you'd simply change the exclusion to point at Project-E, but you wouldn't 
+  move the exclusion down to Project-D...you cannot change Project-D's POM. 
+  If you could, you would use optional dependencies instead of exclusions, 
+  or split Project-D up into multiple subprojects, each with nothing but 
+  normal dependencies. 
+
++---+
+
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>sample.ProjectA</groupId>
+  <artifactId>Project-A</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+  ...
+  <dependencies>
+    <dependency>
+      <groupId>sample.ProjectB</groupId>
+      <artifactId>Project-B</artifactId>
+      <version>1.0-SNAPSHOT</version>
+      <exclusions>
+        <exclusion>
+         <groupId>sample.ProjectE</groupId> <!-- Exclude Project-E from 
Project-B -->
+         <artifactId>Project-E</artifactId>
+       </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+</project>
+
++---+
+
+** Why exclusions are made on a per-dependency basis, rather than at the POM 
level
+  
+  This is mainly done to be sure the dependency graph is predictable, and to 
+  keep inheritance effects from excluding a dependency that should not be 
+  excluded. If you get to the method of last resort and have to put in an 
+  exclusion, you should be absolutely certain which of your dependencies is 
+  bringing in that unwanted transitive dependency.


Reply via email to