1. Introduction

Play is a modern web application framework. The Play plugin adds support for building, testing and running Play applications with Gradle.

This plugin is different from the Play plugin shipped with the Gradle distribution. It’s developed and shipped independently from the Gradle core functionality and does not use the software model. See the migration section for guidance on moving your project to this plugin.

1.1. Requirements

The Play plugin defines the following requirements for a consuming build.

  • The build has to be run with Java 8 or higher.

  • The build has to use Gradle 5.0 or higher.

  • The supported Play versions are 2.4.x, 2.5.x, 2.6.x, 2.7.x, and 2.8.x.

1.2. Limitations

The Play plugin currently has a few limitations.

  • The plugin does not yet support aggregate reverse routes introduced in Play 2.4.x.

  • A given project may only define a single Play application. This means that a single project cannot build more than one Play application. However, a multi-project build can have many projects that each define their own Play application.

  • Support for generating IDE configurations for Play applications is limited to IDEA.

1.3. Applying the plugin

To use the Play plugin, include the following in your build script to apply the org.gradle.playframework plugin. Currently, the plugin is only available on the Gradle plugin portal.

Defining the Lightbend repositories is necessary.

build.gradle
plugins {
    id 'org.gradle.playframework' version '0.14'
}

repositories {
    mavenCentral()
    maven {
        name "lightbend-maven-release"
        url "https://repo.lightbend.com/lightbend/maven-releases"
    }
    ivy {
        name "lightbend-ivy-release"
        url "https://repo.lightbend.com/lightbend/ivy-releases"
        layout "ivy"
    }
}

2. Plugin conventions

2.1. Play framework

By default, Gradle uses Play 2.6.25, Scala 2.12 and the version of Java used to start the build. A Play application can select a different version by configuring the plugin extension.

The following versions of Play and Scala are supported:

Table 1. Play supported versions
Play Scala Java

2.8.x

2.12 and 2.13

1.8

2.7.x

2.11, 2.12 and 2.13

1.8

2.6.x

2.11 and 2.12

1.8

2.5.x

2.11

1.8

2.4.x

2.10 and 2.11

1.8

2.3.x

2.10 and 2.11

1.6, 1.7 and 1.8

2.2. Project layout

The Play plugin follows the typical Play application layout. You can configure source sets to include additional directories or change the defaults.

├── app                 → Application source code.
│   ├── assets          → Assets that require compilation.
│   │   └── javascripts → JavaScript source code to be minified.
│   ├── controllers     → Application controller source code.
│   ├── models          → Application business source code.
│   └── views           → Application UI templates.
├── build.gradle        → Your project's build script.
├── conf                → Main application configuration file and routes files.
├── public              → Public assets.
│   ├── images          → Application image files.
│   ├── javascripts     → Typically JavaScript source code.
│   └── stylesheets     → Typically CSS source code.
└── test                → Test source code.

2.3. Tasks

The Play plugin hooks into the normal Gradle lifecycle tasks such as assemble, check and build, but it also adds several additional tasks which form the lifecycle of a Play project:

2.3.1. Lifecycle tasks

distTask

Depends on: createMainZipDist, createMainTarDist

Assembles the Play distribution.

stageTask

Depends on: stageMainDist

Stages the Play distribution.

2.3.2. Running and testing tasks

The plugin also provides tasks for running, testing and packaging your Play application.

runPlayPlayRun

Depends on: build to build Play application.

Runs the Play application for local development. See how this works with continuous build.

testTest

Depends on: testClasses to compile Play sources.

Runs JUnit/TestNG tests for the Play application.

2.3.3. Distribution tasks

createMainStartScriptsCreateStartScripts

Generates scripts to run the Play application distribution.

stageMainDistCopy

Depends on: assemble, createMainStartScripts

Copies all jar files, dependencies and scripts into a staging directory.

createMainZipDistZip

Bundles the Play application as a standalone distribution packaged as a zip.

createMainTarDistTar

Bundles the Play application as a standalone distribution packaged as a tar.

2.3.4. Source set tasks

For the different types of sources in a Play application, the plugin adds the following compilation tasks.

compileScalaScalaCompile

Depends on: Scala and Java

Compiles all Scala and Java sources defined by the Play application.

compilePlayTwirlTemplatesTwirlCompile

Depends on: Twirl templates

Compiles Twirl templates with the Twirl compiler. Gradle supports all of the built-in Twirl template formats (HTML, XML, TXT and JavaScript). Twirl templates need to match the pattern *.scala.*.

compilePlayRoutesRoutesCompile

Depends on: Play Route files

Compiles routes files into Scala sources.

minifyPlayJavaScriptJavaScriptMinify

Depends on: JavaScript files

Minifies JavaScript files with the Google Closure compiler.

2.4. Source sets

One type of element that describes the application are the source sets that define where the application controller, route, template and model class source files should be found. These source sets are logical groupings of files of a particular type and a default source set for each type is created when the Play plugin is applied.

Table 2. Default Play source sets
Source Set Type Directory Filters

java

SourceSet

app

**/*.java

scala

SourceSet

app

**/*.scala

routes

RoutesSourceSet

conf

routes, *.routes

twirl

TwirlSourceSet

app

**/*.scala.*

javaScript

JavaScriptSourceSet

app/assets

**/*.js

2.5. Dependency configurations

You can add compile, test and runtime dependencies to a Play application through the standard Configurations created by the Java plugin.

If you are coming from SBT, the Play SBT plugin provides short names for common dependencies. For instance, if your project has a dependency on ws, you will need to add a dependency to com.typesafe.play:play-ws_2.11:2.3.9 where 2.11 is your Scala version and 2.3.9 is your Play framework version.

Other dependencies that have short names, such as jackson may actually be multiple dependencies. For those dependencies, you will need to work out the dependency coordinates from a dependency report.

You can add dependencies to those configurations as needed.

The Play plugin creates a custom configuration and assigns Play dependencies automatically based on the configuration of the Play platform. The custom configuration is not meant for assigning dependencies from a project using the plugin.

  • play is used for Play-specific compile time dependencies.

2.6. Generated files comments

Files generated by Twirl and Route compilers contain comments which are changing across builds (absolute path and date depending on the framework version), this prevents tasks using those files as inputs to benefit from build cache. The plugin is post-processing those files to remove timestamp and convert absolute paths to relative paths.

3. Typical usage patterns

3.1. Adding dependencies

Your Play application might need additional dependencies. The Java plugin exposes standard configurations for adding dependencies.

build.gradle
dependencies {
    implementation "commons-lang:commons-lang:2.6"
    implementation "com.typesafe.play:play-guice_2.12:2.6.25"
    implementation "ch.qos.logback:logback-classic:1.2.3"
    testImplementation "org.scalatestplus.play:scalatestplus-play_2.12:3.1.2"
}

3.2. Running an application

The runPlay task starts the Play application under development. During development it is beneficial to execute this task as a continuous build. Continuous build is a generic feature that supports automatically re-running a build when inputs change. The runPlay task is “continuous build aware” in that it behaves differently when run as part of a continuous build.

When not run as part of a continuous build, the runPlay task will block the build. That is, the task will not complete as long as the application is running. When running as part of a continuous build, the task will start the application if not running and otherwise propagate any changes to the code of the application to the running instance. This is useful for quickly iterating on your Play application with an edit->rebuild->refresh cycle. Changes to your application will not take affect until the end of the overall build.

To enable continuous build, run Gradle with -t runPlay or --continuous runPlay.

Users of Play used to such a workflow with Play’s default build system should note that compile errors are handled differently. If a build failure occurs during a continuous build, the Play application will not be reloaded. Instead, you will be presented with an exception message. The exception message will only contain the overall cause of the build failure. More detailed information will only be available from the console.

3.3. Packaging a distribution

Gradle provides the capability to package your Play application so that it can easily be distributed and run in a target environment. The distribution package (zip file) contains the Play binary jars, all dependencies, and generated scripts that set up the classpath and run the application in a Play-specific Netty container.

The distribution can be created by running the dist lifecycle task and places the distribution in the $buildDir/distributions directory. Alternatively, one can validate the contents by running the stage lifecycle task which copies the files to the $buildDir/stage directory using the layout of the distribution package.

You can add additional files to the distribution.

3.4. Modeling multi-project applications

Play applications can be built in multi-project builds as well. Simply apply the org.gradle.playframework plugin in the appropriate subprojects and create any project dependencies on the play configuration.

build.gradle
dependencies {
    implementation project(":admin")
    implementation project(":user")
    implementation project(":util")
}

3.5. Building an application in an IDE

If you want to generate IDE metadata configuration for your Play project, you need to apply the appropriate IDE plugin. Gradle supports generating IDE metadata for IDEA only for Play projects at this time.

To generate IDEA’s metadata, apply the idea plugin along with the org.gradle.playframework plugin.

build.gradle
plugins {
    id 'org.gradle.playframework' version '0.14'
}

Source code generated by routes and Twirl templates cannot be generated by IDEA directly, so changes made to those files will not affect compilation until the next Gradle build. You can run the Play application with Gradle in continuous build to automatically rebuild and reload the application whenever something changes.

4. Plugin configuration

4.1. Targeting a Play version

A Play application can be configured to target a certain version of Play. You can configure the Play, Scala and Java version individually with the help of the PlayPlatform which is exposed by the method PlayExtension.platform(org.gradle.api.Action).

build.gradle
play {
    platform {
        playVersion = '2.6.14'
        scalaVersion = '2.11'
        javaVersion = JavaVersion.VERSION_1_9
    }
}

4.2. Configuring routes style

If your Play application’s router uses dependency injection to access your controllers, you’ll need to configure your application to not use the default static router. Under the covers, the Play plugin is using the InjectedRoutesGenerator instead of the default StaticRoutesGenerator to generate the router classes.

The injected router is only supported in Play Framework 2.4 or better.

build.gradle
play {
    injectedRoutesGenerator = true
}

4.3. Adding source directories

You can add extra source directories to the default source sets provided by this plugin. Gradle will automatically add them to the appropriate compile tasks. You can further configure the default source sets to do things like add new directories, add filters, etc.

build.gradle
sourceSets {
    main {
        scala {
            srcDir 'additional/java'
        }
        javaScript {
            srcDir 'additional/javascript'
            exclude '**/old_*.js'
        }
    }
}

4.4. Configuring compiler options

If your Play application requires additional Scala compiler flags, you can add these arguments directly to the Scala compiler task.

build.gradle
tasks.withType(ScalaCompile) {
    scalaCompileOptions.additionalParameters = ["-feature", "-language:implicitConversions"]
}

4.5. Adding additional files to the distribution

You can add additional files to the distribution package using the Distribution API.

build.gradle
distributions {
    main {
        contents {
            from("README.md")
            from("scripts") {
                into "bin"
            }
        }
    }
}

5. Migrating from Gradle’s standard Play plugin

The following features are not available in this plugin:

  • Any features of the Gradle software model and its plugin ecosystem.

  • The custom configurations playTest and playRun do not exist anymore. Use the standard configurations implementation, testImplementation and runtime of the Java/Scala plugin instead.

  • The extension does not allow for configuring a target platform. You will need to configure Play, Scala and Java version individually.

  • Adding new source sets of a specific type is a built-in feature of the software model. This functionality is currently not available.

  • The concept of an "asset" does not exist and therefore cannot be used to configure a custom asset pipeline.

  • Source sets cannot be added by type. You will need to add additional source directories to the existing source sets provided by the plugin.

  • The CoffeeScript plugin is not available anymore.

6. Change Log

v0.14 (2023-06-28)

  • Add configuration to post-process routes comments (issue #109).

  • Remove use of more internal APIs

v0.13 (2023-01-24)

  • Remove usage of internal Gradle API org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact

  • Update wrapper to Gradle 6.9.3

  • Clean unused imports

v0.12 (2021-06-10)

  • Fix compatibility with upcoming Gradle 8.0

  • Thank you to our community contributors:

  • iaco86 - Add support for Play 2.8

v0.11 (2021-01-22)

  • Fix compatibility with upcoming Gradle 7.0

v0.10 (2020-10-15)

  • Thank you to our community contributors:

  • cmsr - TwirlCompiler support for dependency injection

  • novokrest - NPE when compiling routes with Play 2.3.X

  • clemstoquart - Fix deprecated code relying on ProjectLayout.configurableFiles()

  • arjunchhabra - Add preliminary support for Play 2.7.X

  • JospehChiu - Release automation

v0.9 (2019-08-20)

  • Add workaround for multiple SLF4J bindings on classpath for runPlay

v0.8 (2019-08-07)

  • Restore compatibility with Gradle 5.1.1 and added test coverage for Gradle 5.1.1-5.5.1

v0.7 (2019-08-02)

  • Update to build with Gradle 5.5.1

  • Use the Provider-API to carry dependencies for PlayRun instead of explicit dependencies. Previously, PlayRun depended on build explicitly, which required tests to run before PlayRun could run.

v0.6 (2019-04-29)

  • Generate a proper Class-Path manifest entry with runtime classpath

v0.5 (2019-04-10)

  • IDEA plugin should allow users to modify source directories

v0.4 (2019-02-18)

  • Rework plugins to rely on Java/Scala plugin configurations

v0.3 (2019-02-08)

  • Move classes from package org.gradle.scala.internal.reflect from Gradle core into plugin code base.

v0.2 (2019-02-08)

  • Ensure compatibility with Gradle 5.2 (issue #82).

  • Fix test code in basic and advanced samples (issue #74).

  • Improve Javadoc for public API (issue #80).

  • Samples can be run as standalone projects (issue #76).

v0.1 (2018-12-14)

  • Initial version of plugin.