dependencies

Dependency, dependent or depend may refer to: read more at WikiPedia

  • apache_maven

    What can you do to avoid that when you use one Maven dependency, to also inherit some other undesirable older
    dependency (which is to say from an older transitive dependency).

    The fix to this is to add an exclusion to the dependency in question.
    For example, if we start with a dependency upon version 1.2 of the jxpath library:

    <dependency>
       <groupId>common-jxpath</groupId>
       <artifactId>common-jxpath</artifactId>
       <version>1.2</version>
       <scope>compile</scope> <!-- default scope for sake of example-->
    </dependency>

    This dependency to jxpath 1.2 will bring in an old version of log4j 3.8. In order to ensure that I am using the latest
    versions of log4j (4.4),

    I need to put in an exclusion for these transitive dependencies of common-jxpath, which I do as follows:

    <dependency>
       <groupId>common-jxpath</groupId>
       <artifactId>common-jxpath</artifactId>
       <version>1.2</version>
       <scope>compile</scope> 
       <exclusions>
          <exclusion>
             <artifactId>junit</artifactId>
             <groupId>junit</groupId>
          </exclusion>
          <!-- I can put many of these here -->
    </exclusions> </dependency>

    Having excluded them, they will be any longer in the build.

    Now, there is still too many thing that can occur in the background

    • Another 3rd party artifact may include log4j by using a transitive dependencies, and then you will have to rely/trust transitive
      dependency mediation
    • You can explicitly include the versions that you want in all pom.xml or better in your parent pom.xml

    Transitive dependency mediation

    Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are
    encountered. Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of
    the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it
    explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, until
    Maven 2.0.4 it was not defined which one would win, but since Maven 2.0.5 it's the order in the declaration that counts: the
    first declaration wins.
    "nearest definition" means that the version used will be the closest one to your project in the tree of dependencies, eg. if
    dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A
    because the path from A to D through E is shorter. You could explicitly add a dependency to D 2.0 in A to force the use of D 2.0

    find out what the transitive dependencies are?

    You can't control what you do not know!

    One that can be use during build stage or explicitly use on command line, is the maven plugin maven-dependency-plugin

       <build>
          <plugins>
             <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
             </plugin>
          </plugins>
       </build>

    and then use the goal dependency:tree, so a typical build strategy could look like 

    mvn clean install dependency:tree
    or
    mvn clean install dependency:list   (easier to tokenize in excel sheet)
    So it look like
    With no exclusions

    [INFO] [dependency:tree]
    [INFO] com.test:test:jar:0.0.1-SNAPSHOT
    [INFO] \- commons-jxpath:commons-jxpath:jar:1.2:compile
    [INFO]    +- xerces:xerces:jar:1.2.3:compile
    [INFO]    +- javax.servlet:servlet-api:jar:2.2:compile
    [INFO]    +- junit:junit:jar:3.8:compile
    [INFO]    +- ant:ant-optional:jar:1.5.1:compile
    [INFO]    +- xml-apis:xml-apis:jar:1.0.b2:compile
    [INFO]    +- jdom:jdom:jar:b9:compile
    [INFO]    +- commons-beanutils:commons-beanutils:jar:1.4:compile
    [INFO]    +- commons-logging:commons-logging:jar:1.0:compile
    [INFO]    \- commons-collections:commons-collections:jar:2.0:compile
    [INFO] [dependency:list]
    [INFO]
    [INFO] The following files have been resolved:
    [INFO]    ant:ant-optional:jar:1.5.1:compile
    [INFO]    commons-beanutils:commons-beanutils:jar:1.4:compile
    [INFO]    commons-collections:commons-collections:jar:2.0:compile
    [INFO]    commons-jxpath:commons-jxpath:jar:1.2:compile
    [INFO]    commons-logging:commons-logging:jar:1.0:compile
    [INFO]    javax.servlet:servlet-api:jar:2.2:compile
    [INFO]    jdom:jdom:jar:b9:compile
    [INFO]    junit:junit:jar:3.8:compile
    [INFO]    xerces:xerces:jar:1.2.3:compile
    [INFO]    xml-apis:xml-apis:jar:1.0.b2:compile

     

    With exclusions

    [dependency:tree]
    [INFO] com.test:test:jar:0.0.1-SNAPSHOT
    [INFO] \- commons-jxpath:commons-jxpath:jar:1.2:compile
    [INFO]    +- xerces:xerces:jar:1.2.3:compile
    [INFO]    +- javax.servlet:servlet-api:jar:2.2:compile
    [INFO]    +- ant:ant-optional:jar:1.5.1:compile
    [INFO]    +- xml-apis:xml-apis:jar:1.0.b2:compile
    [INFO]    +- jdom:jdom:jar:b9:compile
    [INFO]    +- commons-beanutils:commons-beanutils:jar:1.4:compile
    [INFO]    +- commons-logging:commons-logging:jar:1.0:compile
    [INFO]    \- commons-collections:commons-collections:jar:2.0:compile
    [INFO] [dependency:list]
    [INFO]
    [INFO] The following files have been resolved:
    [INFO]    ant:ant-optional:jar:1.5.1:compile
    [INFO]    commons-beanutils:commons-beanutils:jar:1.4:compile
    [INFO]    commons-collections:commons-collections:jar:2.0:compile
    [INFO]    commons-jxpath:commons-jxpath:jar:1.2:compile
    [INFO]    commons-logging:commons-logging:jar:1.0:compile
    [INFO]    javax.servlet:servlet-api:jar:2.2:compile
    [INFO]    jdom:jdom:jar:b9:compile
    [INFO]    xerces:xerces:jar:1.2.3:compile
    [INFO]    xml-apis:xml-apis:jar:1.0.b2:compile

     
    see Maven Dependency Plugin
  • I forgot to blog about this presentation at JAZOON 2008, but I did never forget the added value of this plugin. It is not currently in Apache Maven  core but will for sure find its way as an official plugin one day, since it solve elegantly a common problem: technology management

    Maven does not know the concept of an artifact life cycle. Such life cycle status information would allow to extend the dependency management in a new dimension. One could declare whether certain dependencies are actually allowed/forbidden/restricted to be used in a project, enabling effective technology management.

    Currently a plugin is available to achieve this goal:The AssertDepend plugin. It work by adding metadata, additional xml files in artifact group directory.

    The AssertDepend plugin is a Maven extension to perform effective technology management. The plugin checks at build time against lifecycle states defined in metadata on remote repositories in order to inform the developer about inappropriate technology usage (dependency enforcement). Based on a flag the build would either fail or print a warning.


    Technology management benefits and means

    The capability to manage dependencies and technologies on a mature level is essential for software organizations of a certain size. Technology management becomes a key discipline and must be introduced in a careful way to allow for mutual benefits among its stakeholder including developer, management, and customers.

    Artifact lifecycle management

    To perform effective technology management, you should keep the number of approved artifacts as small as possible. You cannot remove artifacts from the repository if you want to sustain reproducible builds. Therefore, each artifact in the repository should be marked with a corresponding lifecycle state.

    The proposed main states are (but the plugin is not limited, you can create your own)

    • approved
    • prohibited
    • investigating

    With these states, it solve elegantly the following use cases.

    Scenario 1: Flawed versions
    It turns out that my-app-1.4.2.jar contains a serious security issue and is therefore flawed. Clients of this JAR should actually switch to a newer version my-app-1.4.3.jar which fixes the bug and which is safe to use.

    Scenario 2: Decommissioning
    Let's assume that my-app-1.4.2.jar is not supported anymore and projects should actually switch to a new release stream
    (my-app-2.x.y.jar).

    Scenario 3: Restricted usage
    Consider a library which has a restricted set of client projects, e.g. only certain projects are allowed to depend on a specific artifact.

    Usage

    Artifact lifecycle metadata must be placed in a file named maven-artifact-lifecycle.xml in the corresponding group directory. For instance, if you want to define lifecycle information for struts, the corresponding metadata file is located here: struts/struts/maven-artifact-lifecycle.xml

    This plugin can be downloaded at http://madp.sourceforge.net/index.html