<commit_before><!--
  ~ Copyright 2009 the original author or authors.
  ~
  ~ 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.
  -->
<chapter id='dependency_management'>
    <title>Dependency Management</title>
    <section id='sec:Introduction'>
        <title>Introduction</title>
        <para>This chapter gives an overview of issues related with dependency management and presents how Gradle can be used to overcome them.
        </para>
        <para>Gradle offers a very good support for dependency management. If you are familiar with Maven or Ivy approach you will be delighted to learn that:
        <itemizedlist>
            <listitem>
                <para>All the concepts that you already know and like are still there and are fully supported by Gradle. The current dependency management solutions all require to work with XML descriptor files and are usually
        based on remote repositories for downloading the dependencies. Gradle fully supports this approach.
                </para>
            </listitem>
            <listitem>
                <para>Gradle works <emphasis>perfectly</emphasis> with your existent dependency management
                    infrastructure, be it Maven or Ivy. All the repositories you have set up with your custom POM or
                    ivy files can be used as they are. No changes necessary.
                </para>
            </listitem>
            <listitem>
                <para>Additionally, Gradle offers a simpler approach, which might be better suited for some projects.
                </para>
            </listitem>
        </itemizedlist>
        </para>
    </section>
    <section id='sec:dependency_management_overview'>
        <title>Dependency management overview</title>
        <para>We think dependency management is very important for almost any project. Yet the kind of dependency
            management you need depends on the complexity and the environment of your project. Is your project a
            distribution or a library? Is it part of an enterprise environment, where it is integrated into other
            projects builds or not? But all types of projects share the following requirements:
        </para>
        <itemizedlist>
            <listitem>
                <para>The version of the jar must be easy to recognize. Sometimes the version is in the Manifest file of
                    the jar, often not. And even if, it is rather painful to always look into the Manifest file to learn
                    about the version. Therefore we think that you should only use jars which have their version as part
                    of their file name.
                </para>
            </listitem>
            <listitem>
                <para>It hopes to be clear what are the first level dependencies and what are the transitive ones. There
                    are different ways to achieve this. We will look at this later.
                </para>
            </listitem>
            <listitem>
                <para>Conflicting versions of the same jar should be detected and either resolved or cause an exception.
                </para>
            </listitem>
        </itemizedlist>
        <section id='sub:versioning_the_jar_name'>
            <title>Versioning the jar name</title>
            <para>Why do we think this is necessary? Without a dependency management as described above, your are likely
                to burn your fingers sooner or later. If it is unclear which version of a jar your are using, this can
                introduce subtle bugs which are very hard to find. For example there might be a project which uses
                Hibernate 3.0.4. There are some problems with Hibernate so a developer installs version 3.0.5 of
                Hibernate on her machine. This did not solve the problem but she forgot to roll back Hibernate to 3.0.4.
                Weeks later there is an exception on the integration machine which can't be reproduced on the developer
                machine. Without a version in the jar name this problem might take a long time to debug. Version in the
                jar names increases the expressiveness of your project and makes it easier to maintain.
            </para>
        </section>
        <section id='sub:transitive_dependency_management'>
            <title>Transitive dependency management</title>
            <para>Why is transitive dependency management so important? If you don't know which dependencies are first
                level dependencies and which ones are transitive you will soon lose control over your build. Even
                Gradle has already 20+ jars. An enterprise project using Spring, Hibernate, etc. easily ends up with
                100+ jars. There is no way to memorize where all these jars come from. If you want to get rid of a first
                level dependency you can't be sure which other jars you should remove. Because a dependency of a
                first level dependency might also be a first level dependency itself. Or it might be a transitive
                dependency of another of your first level dependencies. Many first level dependencies are runtime
                dependencies and the transitive dependencies are of course all runtime dependencies. So the compiler
                won't help you much here. The end of the story is, as we have seen very often, no one dares to remove
                any jar any longer. The project classpath is a complete mess and if a classpath problem arises, hell on
                earth invites you for a ride. In one of my former projects, I found some ldap related jar in the
                classpath, whose sheer presence, as I found out after much research, accelerated LDAP access. So
                removing this jar would not have led to any errors at compile or runtime.
            </para>
            <para>Gradle offers you different ways to express what are first level and what are transitive dependencies.
                Gradle allows you for example to store your jars in CVS or SVN without XML descriptor files and still
                use transitive dependency management. Gradle also validates your dependency hierarchy against the
                reality of your code by using only the first level dependencies for compiling.
            </para>
        </section>
        <section id='sub:version_conflicts'>
            <title>Version conflicts</title>
            <para>In your dependency description you tell Gradle which version of a dependency is needed by another
                dependency. This frequently leads to conflicts. Different dependencies rely on different versions of
                another dependency. The JVM unfortunately does not offer yet any easy way, to have different versions of
                the same jar in the classpath (see <xref linkend='sub:dependency_management_and_java'/>).
                Gradle offers following conflict resolution strategies:
                <itemizedlist>
                    <listitem><emphasis>Newest</emphasis> - used by default by Gradle - the newest version of the dependency is used.</listitem>
                    <listitem><emphasis>Fail</emphasis> - fail eagerly on version conflict.
                        Useful if you need extra control and manage the conflicts manually.</listitem>
                </itemizedlist>
                See <apilink class='org.gradle.api.artifacts.ResolutionStrategy'/> for reference on managing the conflict resolution strategies.
                To deal with problems due to version conflicts, reports with dependency graphs are also very helpful.
                Such reports are another feature of dependency management.
            </para>
        </section>
        <section id='sub:dynamic_versions_and_changing_modules'>
            <title>Dynamic Versions and Changing Modules</title>
            <para>Sometimes, you always want to use the latest version of a particular dependency, or the latest in a range of versions.
                You can easily do this using a <emphasis>dynamic version</emphasis>. A dynamic version can be either a version range (eg. <literal>2.+</literal>)
                or it can be a placeholder for the latest version available (eg. <literal>latest.integration</literal>).
            </para>
            <para>Alternatively, sometimes the module you request can change over time, even for the same version.
                An example of this type of <emphasis>changing module</emphasis> is a maven <literal>SNAPSHOT</literal> module,
                which always points at the latest artifacts published.
            </para>
            <para>
                The main difference between a <emphasis>dynamic version</emphasis> and a <emphasis>changing module</emphasis> is
                that when you resolve a <emphasis>dynamic version</emphasis>, you'll get the real, static version as the module name.
                When you resolve a <emphasis>changing module</emphasis>, the artifacts are named using the version you requested,
                but the underlying artifacts may change over time.
            </para>
            <para>By default, Gradle caches dynamic versions for 24 hours. You can change this cache expiry time for a configuration using the resolution strategy.<commit_msg>Polished the documentation around the forcing module versions. Added information to the user guide with links to the dsl reference.<commit_after><!--
  ~ Copyright 2009 the original author or authors.
  ~
  ~ 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.
  -->
<chapter id='dependency_management'>
    <title>Dependency Management</title>
    <section id='sec:Introduction'>
        <title>Introduction</title>
        <para>This chapter gives an overview of issues related with dependency management and presents how Gradle can be used to overcome them.
        </para>
        <para>Gradle offers a very good support for dependency management. If you are familiar with Maven or Ivy approach you will be delighted to learn that:
        <itemizedlist>
            <listitem>
                <para>All the concepts that you already know and like are still there and are fully supported by Gradle. The current dependency management solutions all require to work with XML descriptor files and are usually
        based on remote repositories for downloading the dependencies. Gradle fully supports this approach.
                </para>
            </listitem>
            <listitem>
                <para>Gradle works <emphasis>perfectly</emphasis> with your existent dependency management
                    infrastructure, be it Maven or Ivy. All the repositories you have set up with your custom POM or
                    ivy files can be used as they are. No changes necessary.
                </para>
            </listitem>
            <listitem>
                <para>Additionally, Gradle offers a simpler approach, which might be better suited for some projects.
                </para>
            </listitem>
        </itemizedlist>
        </para>
    </section>
    <section id='sec:dependency_management_overview'>
        <title>Dependency management overview</title>
        <para>We think dependency management is very important for almost any project. Yet the kind of dependency
            management you need depends on the complexity and the environment of your project. Is your project a
            distribution or a library? Is it part of an enterprise environment, where it is integrated into other
            projects builds or not? But all types of projects share the following requirements:
        </para>
        <itemizedlist>
            <listitem>
                <para>The version of the jar must be easy to recognize. Sometimes the version is in the Manifest file of
                    the jar, often not. And even if, it is rather painful to always look into the Manifest file to learn
                    about the version. Therefore we think that you should only use jars which have their version as part
                    of their file name.
                </para>
            </listitem>
            <listitem>
                <para>It hopes to be clear what are the first level dependencies and what are the transitive ones. There
                    are different ways to achieve this. We will look at this later.
                </para>
            </listitem>
            <listitem>
                <para>Conflicting versions of the same jar should be detected and either resolved or cause an exception.
                </para>
            </listitem>
        </itemizedlist>
        <section id='sub:versioning_the_jar_name'>
            <title>Versioning the jar name</title>
            <para>Why do we think this is necessary? Without a dependency management as described above, your are likely
                to burn your fingers sooner or later. If it is unclear which version of a jar your are using, this can
                introduce subtle bugs which are very hard to find. For example there might be a project which uses
                Hibernate 3.0.4. There are some problems with Hibernate so a developer installs version 3.0.5 of
                Hibernate on her machine. This did not solve the problem but she forgot to roll back Hibernate to 3.0.4.
                Weeks later there is an exception on the integration machine which can't be reproduced on the developer
                machine. Without a version in the jar name this problem might take a long time to debug. Version in the
                jar names increases the expressiveness of your project and makes it easier to maintain.
            </para>
        </section>
        <section id='sub:transitive_dependency_management'>
            <title>Transitive dependency management</title>
            <para>Why is transitive dependency management so important? If you don't know which dependencies are first
                level dependencies and which ones are transitive you will soon lose control over your build. Even
                Gradle has already 20+ jars. An enterprise project using Spring, Hibernate, etc. easily ends up with
                100+ jars. There is no way to memorize where all these jars come from. If you want to get rid of a first
                level dependency you can't be sure which other jars you should remove. Because a dependency of a
                first level dependency might also be a first level dependency itself. Or it might be a transitive
                dependency of another of your first level dependencies. Many first level dependencies are runtime
                dependencies and the transitive dependencies are of course all runtime dependencies. So the compiler
                won't help you much here. The end of the story is, as we have seen very often, no one dares to remove
                any jar any longer. The project classpath is a complete mess and if a classpath problem arises, hell on
                earth invites you for a ride. In one of my former projects, I found some ldap related jar in the
                classpath, whose sheer presence, as I found out after much research, accelerated LDAP access. So
                removing this jar would not have led to any errors at compile or runtime.
            </para>
            <para>Gradle offers you different ways to express what are first level and what are transitive dependencies.
                Gradle allows you for example to store your jars in CVS or SVN without XML descriptor files and still
                use transitive dependency management. Gradle also validates your dependency hierarchy against the
                reality of your code by using only the first level dependencies for compiling.
            </para>
        </section>
        <section id='sub:version_conflicts'>
            <title>Version conflicts</title>
            <para>In your dependency description you tell Gradle which version of a dependency is needed by another
                dependency. This frequently leads to conflicts. Different dependencies rely on different versions of
                another dependency. The JVM unfortunately does not offer yet any easy way, to have different versions of
                the same jar in the classpath (see <xref linkend='sub:dependency_management_and_java'/>).</para>
            <para>Gradle offers following conflict resolution strategies:
                <itemizedlist>
                    <listitem><emphasis>Newest</emphasis> - used by default by Gradle - the newest version of the dependency is used.
                    This strategy has been in Gradle since early days.
                    </listitem>
                    <listitem><emphasis>Fail</emphasis> - fail eagerly on version conflict.
                        Useful if you need extra control and manage the conflicts manually.
                        Introduced in <code>1.0-milestone-6</code>. See <apilink class='org.gradle.api.artifacts.ResolutionStrategy'/> for reference on managing the conflict resolution strategies.
                    </listitem>
                </itemizedlist>
                Gradle provides means to resolve version conflicts:
                <itemizedlist>
                    <listitem>
                        Configuring a first level dependency as <emphasis>forced</emphasis>.
                        The feature has been in Gradle since early days.
                        This approach is useful if the dependency incurring conflict is already a first level dependency.
                        See examples in <apilink class='org.gradle.api.artifacts.dsl.DependencyHandler'/>
                    </listitem>
                    <listitem>
                        Configuring any dependency (transitive or not) as <emphasis>forced</emphasis>.
                        The feature was introduced in <code>1.0-milestone-7</code>.
                        This approach is useful if the dependency incurring conflict is a transitive dependency.
                        It also can be used to force versions of first level dependencies.
                        See examples in <apilink class='org.gradle.api.artifacts.ResolutionStrategy'/>
                    </listitem>
                </itemizedlist>
                To deal with problems due to version conflicts, reports with dependency graphs are also very helpful.
                Such reports are another feature of dependency management.
            </para>
        </section>
        <section id='sub:dynamic_versions_and_changing_modules'>
            <title>Dynamic Versions and Changing Modules</title>
            <para>Sometimes, you always want to use the latest version of a particular dependency, or the latest in a range of versions.
                You can easily do this using a <emphasis>dynamic version</emphasis>. A dynamic version can be either a version range (eg. <literal>2.+</literal>)
                or it can be a placeholder for the latest version available (eg. <literal>latest.integration</literal>).
            </para>
            <para>Alternatively, sometimes the module you request can change over time, even for the same version.
                An example of this type of <emphasis>changing module</emphasis> is a maven <literal>SNAPSHOT</literal> module,
                which always points at the latest artifacts published.
            </para>
            <para>
                The main difference between a <emphasis>dynamic version</emphasis> and a <emphasis>changing module</emphasis> is
                that when you resolve a <emphasis>dynamic version</emphasis>, you'll get the real, static version as the module name.
                When you resolve a <emphasis>changing module</emphasis>, the artifacts are named using the version you requested,
                but the underlying artifacts may change over time.
            </para>
            <para>By default, Gradle caches dynamic versions for 24 hours. You can change this cache expiry time for a configuration using the resolution strategy.
{'fraction_non_alphanumeric': 0.0487563128333412, 'fraction_numerical': 0.002643130221362156, 'mean_word_length': 2.2541852250038397, 'pattern_counts': {'":': 0, '<': 235, '<?xml version=': 0, '>': 235, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6030982', 'n_tokens_mistral': 4741, 'n_tokens_neox': 4439, 'n_words': 2501}