h1. Dependency management

Play’s dependency management system allows you to express your application’s external dependencies in a single @dependencies.yml@ file. 

A Play application can have three kinds of dependencies:

* The Play framework itself, since a Play application always depends on the Play framework.
* Some Play framework modules: CRUD and secure module
* Any Java library, provided as **JAR** file installed in your application’s @lib/@ directory.
* A Play module (in fact an application fragment) installed in your application’s @modules/@ directory.

Once you have expressed these dependencies in your application’s @conf/dependencies.yml@ file, Play will resolve, download and install all required dependencies.

h2. <a name="format">Dependency format</a>

A dependency is described by :
* an organisation a name, 
* a revision number 
* a classifier _(optional)_

In the @dependencies.yml@ file you will write it like this:

bc. organisation -> name revision [classifier]

So, for instance version 1.0 of the "Play PDF module":https://www.playframework.com/modules/pdf is expressed like this:

bc. play -> pdf 1.0

Sometimes the organisation name exactly matches the dependency name, as is the case for "commons-lang":http://commons.apache.org/lang/:

bc. commons-lang -> commons-lang 2.5

In this case, you can omit the organisation from the dependency declaration:

bc. commons-lang 2.5

When your dependency has a classifier, you can use this:

bc. net.sf.json-lib -> json-lib 2.4 jdk15

For Play and Play framework modules (CRUD and secure module), the revision number is not required:

bc. play
play -> crud
play -> secure

h3. Dynamic revisions

The revision can be fixed (1.2, for instance) or dynamic. A dynamic revision expresses a range of allowed revisions. 

There are many things you can configure: see the "Ivy version-matchers documentation":http://ant.apache.org/ivy/history/2.3.0/settings/version-matchers.html.

For example:
Sub Revision Matcher
* @1.0.+@ matches all revisions starting with '1.0.', like 1.0.1, 1.0.5, 1.0.a
* @1.1+@ matches all revisions starting with '1.1', like 1.1, 1.1.5, but also 1.10, 1.11
Latest (Status) Matcher
* @latest.integration@ matches all versions
* @latest.milestone@ matches all modules having at least 'milestone' as status
* @latest.release@ matches all modules having at least 'release' as status
* @latest.[any status]@ all modules having at least the specified status
Version Range Matcher
* @[1.0,2.0]@ matches all versions greater or equal to 1.0 and lower or equal to 2.0
* @[1.0,2.0[@ matches all versions greater or equal to 1.0 and lower than 2.0
* @]1.0,2.0]@ matches all versions greater than 1.0 and lower or equal to 2.0
* @]1.0,2.0[@ matches all versions greater than 1.0 and lower than 2.0
* @[1.0,)@ matches all versions greater or equal to 1.0
* @]1.0,)@ matches all versions greater than 1.0
* @(,2.0]@ matches all versions lower or equal to 2.0
* @(,2.0[@ matches all versions lower than 2.0

h2. <a name="yml">dependencies.yml</a>

When you create a new Play application, a @dependencies.yml@ descriptor is automatically created in the @conf/@ directory:

bc. # Application dependencies
    
require:
    - play 1.2

The @require@ section list all dependencies needed by your application. Here the new application only depends on **Play version 1.2**. But let’s say your application needs "Google Guava":http://code.google.com/p/guava-libraries/; you would have:

bc. # Application dependencies
    
require:
    - play 1.2
    - com.google.guava -> guava r07

h3. The ‘play dependencies’ command

To ask Play to resolve, download and install the new dependencies, run @play dependencies@:

bc. $ play dependencies
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2, https://www.playframework.com
~ framework ID is gbo
~
~ Resolving dependencies using ~/Documents/coco/conf/dependencies.yml,
~
~ 	com.google.guava->guava r07 (from mavenCentral)
~ 	com.google.code.findbugs->jsr305 1.3.7 (from mavenCentral)
~
~ Downloading required dependencies,
~
~ 	downloaded http://repo1.maven.org/maven2/com/google/guava/guava/r07/guava-r07.jar
~ 	downloaded http://repo1.maven.org/maven2/com/google/code/findbugs/jsr305/1.3.7/jsr305-1.3.7.jar
~
~ Installing resolved dependencies,
~
~ 	lib/guava-r07.jar
~ 	lib/jsr305-1.3.7.jar
~
~ Done!
~

Now Play has downloaded two JARs (**guava-r07.jar**, **jsr305-1.3.7.jar**) from the central Maven repository, and installed them into the application @lib/@ directory. 

Why two jars, since we only declared one dependency? Because Google Guava has a transitive dependency. In fact this dependency is not really required and we would like to exclude it. 

h3. Transitive dependencies

By default, any transitive dependencies are automatically retrieved. But there are several ways to exclude them if needed.

1. You can disable transitive dependencies for a particular dependency:

bc. # Application dependencies
    
require:
    - play 1.2
    - com.google.guava -> guava r07:
        transitive: false

2. You can disable transitive dependencies for the whole project:

bc. # Application dependencies
    
transitiveDependencies: false    
    
require:
    - play 1.2
    - com.google.guava -> guava r07

3. You can exclude any specific dependency explicitly:

bc. # Application dependencies
    
require:
    - play 1.2
    - com.google.guava -> guava r07:
        exclude:
            - com.google.code.findbugs -> *

4. You can alter the ant configuration mappings used during resolution. See "Custom Configuration Mappings":#config_mappings

h3(#config_mappings).  Custom Configuration Mappings

By default, Play will use the @default->*@ ant mapping. This means all transtive ant configurations (or maven scopes) are pulled in as dependencies.

You can customize this behavior by using the @configurations@ block in @dependencies.yml@:

bc. # Application dependencies
    
configurations:
    - optional:
        exclude: true

This will map to @default -> *, !optional@, or all configurations except @optional@. The way this functions is if no configs are provided then the default mapping of @default -> *@ is used. If only exclude mappings are provided, then the mapping becomes @default -> *, !excludedConfig1, !excludedConfig2,....@. Ivy will then depend on all configurations that are not excluded. If at least one non-excluded configuration is provided, then the listed configurations are all that will be used. For example:

bc. # Application dependencies
    
configurations:
    - compile
    - runtime
    - optional:
        exclude: true

This will map to @default -> compile, runtime, !optional@.

For more information on ant configuration mapping, please refer to the <a href="http://ant.apache.org/ivy/history/latest-milestone/ivyfile/configurations.html" target="_blank">ant documentation</a>

h3. Keep lib/ and modules/ directory in sync

Now if you run @play dependencies@ again, the findbugs dependency will be omitted:

bc. $ play deps
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2, https://www.playframework.com
~ framework ID is gbo
~
~ Resolving dependencies using ~/Documents/coco/conf/dependencies.yml,
~
~ 	com.google.guava->guava r07 (from mavenCentral)
~
~ Installing resolved dependencies,
~
~ 	lib/guava-r07.jar
~
~ ********************************************************************
~ WARNING: Your lib/ and modules/ directories and not synced with 
~ current dependencies (use --sync to automatically delete them)
~
~ 	Unknown: ~/Documents/coco/lib/jsr305-1.3.7.jar
~ ********************************************************************
~
~ Done!
~

However the **jsr305-1.3.7.jar** artifact downloaded before is still present in the application @lib/@ directory. 

To keep the @lib/@ and @modules/@ directory synced with the dependency management system, you can specify the @--sync@ command to the @dependencies@ command:

bc. play dependencies --sync

If you run this command again the unwanted **JAR** will be deleted.

When you deploy an application in production, you can reduce the size of its modules by removing module source code and documentation. You can do this by adding the @--forProd@ option to the command:

bc. play dependencies --forProd

This removes the @documentation/@, @src/@, @tmp/@, @*sample*/@ and @*test*/@ directories from each module.


h2. <a name="conflicts">Conflict resolution</a>

Whenever two components need different revisions of the same dependency, the conflicts manager will choose one. The default is to keep the latest revision and to evict the others. 

But there is an exception. When a core dependency of Play framework itself is involved in a conflict, the version available in @$PLAY/framework/lib@ is preferred. For instance, Play depends on @commons-lang 2.5@. If your application requires @commons-lang 3.0@:

bc. # Application dependencies
    
require:
    - play 1.2
    - com.google.guava -> guava r07:
        transitive: false
    - commons-lang 3.0

Running @play dependencies@ will evict @commons-lang 3.0@ even if this version is newer:

bc. play dependencies
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2, https://www.playframework.com
~ framework ID is gbo
~
~ Resolving dependencies using ~/Documents/coco/conf/dependencies.yml,
~
~ 	com.google.guava->guava r07 (from mavenCentral)
~
~ Some dependencies have been evicted,
~
~	commons-lang 3.0 is overridden by commons-lang 2.5
~
~ Installing resolved dependencies,
~
~ 	lib/guava-r07.jar
~
~ Done!
~

Also, note that dependencies already available in @$PLAY/framework/lib@ will not be installed in your application’s @lib/@ directory.

Sometimes you want to force a specific dependency version, either to override a core dependency or to choose another revision that the latest version available. 

So you can specify the @force@ option on any dependency:

bc. # Application dependencies
    
require:
    - play 1.2
    - com.google.guava -> guava r07:
        transitive: false
    - commons-lang 3.0:
        force: true

h2. <a name="repositories">Adding new repositories</a>

By default, Play will search for **JAR** dependencies in the "central Maven repository":http://repo1.maven.org/maven2/, and will search for **Play modules** in the "central Play modules repository":https://www.playframework.com/modules. 

You can, of course, specify new custom repositories in the @repositories@ section:

bc. # Application dependencies
    
require:
    - play 1.2
    - com.google.guava -> guava r07:
        transitive: false
    - commons-lang 3.0:
        force: true
    - com.zenexity -> sso 1.0
        
# My custom repositories
repositories:
    
    - zenexity:
        type:       http
        artifact:   "http://www.zenexity.com/repo/[module]-[revision].zip"
        contains:
            - com.zenexity -> *

Using this configuration all dependencies of the @com.zenexity@ organisation will be retrieved and downloaded from a remote HTTP server.

h3. Maven repositories

You can also add maven2-compatible repositories using the @iBiblio@ type, like this:

bc. # Application dependencies
    
require:
    - play
    - play -> scala 0.8
    - org.jbpm -> jbpm-persistence-jpa 5.0.0:
        exclude:
            - javassist -> javassist *
            - org.hibernate -> hibernate-annotations *
            - javax.persistence -> persistence-api *
repositories:
    - jboss:
        type: iBiblio
        root: "http://repository.jboss.org/nexus/content/groups/public-jboss/"
        contains:
            - org.jbpm -> *
            - org.drools -> *

h3. Local repositories

Finally and probably foremost, you may want to define a repository that references local modules. With this scenario, dependencies work very much like @application.conf@’s module resolution (now deprecated).

So given the following folder structure,

bc. myplayapp/
myfirstmodule/
mysecondmodule/

The following @myplayapp/conf/depencencies.yml@ will achieve its goal.

bc. # Application dependencies
    
require:
    - play
    - myfirstmodule -> myfirstmodule
    - mysecondmodule -> mysecondmodule
    
repositories:
    - My modules:
        type:       local
        artifact:   ${application.path}/../[module]
        contains:
            - myfirstmodule
            - mysecondmodule

Note: don't forget to run @play dependencies myplayapp@.


h3. Custom ivy settings

Play is using Ivy under the hood. If you require a special configuration such as setting a proxy, basic authentication for an internal maven nexus repository, you can edit the ivysettings.xml file. It is located in the @.ivy2@ folder in your home directory.

Example 1, you want Ivy to ignore checksums:

bc. <!-- .ivy2/ivysettings.xml -->
<ivysettings>
  <property name="ivy.checksums" value=""/>
</ivysettings>

Example 2, you want to use basic authentication:

bc. <!-- .ivy2/ivysettings.xml -->
<ivysettings>
  <credentials host="maven-repo.xxx" realm="Sonatype Nexus Repository Manager"
    username="user" passwd="reallygreatpassword"/>
</ivysettings>

Example 3, reuse local maven repository and repository manager:

bc. <!-- .ivy2/ivysettings.xml -->
<ivy-settings>
  <!-- path to local maven repo and default maven layout -->
  <property name="local-maven2-pattern" 
    value="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[module]-[revision]" 
    override="false" />
 
  <!-- set resolver chain as default -->
  <settings defaultResolver="main" />
 
  <!-- configure caches -->
  <caches repositoryCacheDir="${user.home}/.ivy2/cache">
    <!-- do not cache from local .m2-->
    <cache name="nocache" useOrigin="true" />
    <cache name="default" />
  </caches>
 
  <resolvers>
    <chain name="main">
      <!-- as this is not cached, even changing SNAPSHOT dependencies 
        are resolved correctly -->
      <filesystem name="local-maven-2" m2compatible="true" local="true" 
        cache="nocache">
        <ivy pattern="${local-maven2-pattern}.pom" />
        <artifact pattern="${local-maven2-pattern}(-[classifier]).[ext]" />
      </filesystem>
      <!-- use repository manager as proxy to maven-central
        (and all other repositories)--> 
      <ibiblio name="repomanager" m2compatible="true"
        root="http://your.repomanager.intra/path/to/repo" cache="default"/>
    </chain>
  </resolvers>
</ivy-settings>

There are many things you can configure: see the "Ivy settings documentation":http://ant.apache.org/ivy/history/2.3.0/settings.html.


h3. Clearing the Ivy cache

The Ivy cache can become corrupted, especially when using the @http@ type in the repositories section of @conf/dependencies.yml@. If this happens, and dependency resolution does not work, you can clear the cache with the @--clearcache@ option.

bc. $ play dependencies --clearcache

This is equivalent to @rm -r ~/.ivy2/cache@.


p(note). **Continuing the discussion**

Next: %(next)"Database evolutions":evolutions%.
