├── project ├── build.properties └── plugins.sbt ├── README.md ├── public ├── images │ ├── favicon.png │ ├── external.png │ └── header-pattern.png ├── javascripts │ └── hello.js └── stylesheets │ └── main.css ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── scripts ├── test-sbt └── test-gradle ├── NOTICE ├── test ├── BrowserSpec.scala ├── FunctionalSpec.scala └── UnitSpec.scala ├── conf ├── routes ├── logback.xml └── application.conf ├── app ├── views │ ├── index.scala.html │ ├── main.scala.html │ └── welcome.scala.html ├── filters │ └── ExampleFilter.scala ├── controllers │ ├── HomeController.scala │ ├── CountController.scala │ └── AsyncController.scala ├── services │ ├── Counter.scala │ └── ApplicationTimer.scala └── Module.scala ├── .mergify.yml ├── .travis.yml ├── gradlew.bat ├── .github └── settings.yml ├── gradlew └── LICENSE /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.2.8 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MOVED TO https://github.com/playframework/play-samples 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | // The Play plugin 2 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0") 3 | -------------------------------------------------------------------------------- /public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playframework/play-scala-starter-example/2.7.x/public/images/favicon.png -------------------------------------------------------------------------------- /public/javascripts/hello.js: -------------------------------------------------------------------------------- 1 | if (window.console) { 2 | console.log("Welcome to your Play application's JavaScript!"); 3 | } 4 | -------------------------------------------------------------------------------- /public/images/external.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playframework/play-scala-starter-example/2.7.x/public/images/external.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playframework/play-scala-starter-example/2.7.x/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /public/images/header-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playframework/play-scala-starter-example/2.7.x/public/images/header-pattern.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | logs 3 | target 4 | /.idea 5 | /.idea_modules 6 | /.classpath 7 | /.gradle 8 | /.project 9 | /.settings 10 | /RUNNING_PID 11 | -------------------------------------------------------------------------------- /scripts/test-sbt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | echo "+----------------------------+" 7 | echo "| Executing tests using sbt |" 8 | echo "+----------------------------+" 9 | sbt ++$TRAVIS_SCALA_VERSION test 10 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStorePath=wrapper/dists 5 | zipStoreBase=GRADLE_USER_HOME 6 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Written by Lightbend 2 | 3 | To the extent possible under law, the author(s) have dedicated all copyright and 4 | related and neighboring rights to this software to the public domain worldwide. 5 | This software is distributed without any warranty. 6 | 7 | You should have received a copy of the CC0 Public Domain Dedication along with 8 | this software. If not, see . 9 | -------------------------------------------------------------------------------- /scripts/test-gradle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | # Using cut because TRAVIS_SCALA_VERSION is the full Scala 7 | # version (for example 2.12.4), but Gradle expects just the 8 | # binary version (for example 2.12) 9 | scala_binary_version=$(echo $TRAVIS_SCALA_VERSION | cut -c1-4) 10 | 11 | echo "+------------------------------+" 12 | echo "| Executing tests using Gradle |" 13 | echo "+------------------------------+" 14 | ./gradlew -Dscala.binary.version=$scala_binary_version check -i --stacktrace 15 | -------------------------------------------------------------------------------- /test/BrowserSpec.scala: -------------------------------------------------------------------------------- 1 | import org.scalatestplus.play._ 2 | import org.scalatestplus.play.guice.GuiceOneServerPerTest 3 | 4 | /** 5 | * Runs a browser test using Fluentium against a play application on a server port. 6 | */ 7 | class BrowserSpec extends PlaySpec 8 | with OneBrowserPerTest 9 | with GuiceOneServerPerTest 10 | with HtmlUnitFactory 11 | with ServerProvider { 12 | 13 | "Application" should { 14 | 15 | "work from within a browser" in { 16 | 17 | go to ("http://localhost:" + port) 18 | 19 | pageSource must include ("Your new application is ready.") 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /conf/routes: -------------------------------------------------------------------------------- 1 | # Routes 2 | # This file defines all application routes (Higher priority routes first) 3 | # ~~~~ 4 | 5 | # An example controller showing a sample home page 6 | GET / controllers.HomeController.index 7 | # An example controller showing how to use dependency injection 8 | GET /count controllers.CountController.count 9 | # An example controller showing how to write asynchronous code 10 | GET /message controllers.AsyncController.message 11 | 12 | # Map static resources from the /public folder to the /assets URL path 13 | GET /assets/*file controllers.Assets.versioned(file) 14 | -------------------------------------------------------------------------------- /app/views/index.scala.html: -------------------------------------------------------------------------------- 1 | @* 2 | * This template takes a two arguments, a String containing a 3 | * message to display and an AssetsFinder to locate static assets. 4 | *@ 5 | @(message: String)(implicit assetsFinder: AssetsFinder) 6 | 7 | @* 8 | * Call the `main` template with two arguments. The first 9 | * argument is a `String` with the title of the page, the second 10 | * argument is an `Html` object containing the body of the page. 11 | *@ 12 | @main("Welcome to Play", assetsFinder) { 13 | 14 | @* 15 | * Get an `Html` object by calling the built-in Play welcome 16 | * template and passing a `String` message. 17 | *@ 18 | @welcome(message, style = "scala") 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/filters/ExampleFilter.scala: -------------------------------------------------------------------------------- 1 | package filters 2 | 3 | import javax.inject._ 4 | import play.api.mvc._ 5 | import scala.concurrent.ExecutionContext 6 | 7 | /** 8 | * This is a simple filter that adds a header to all requests. It's 9 | * added to the application's list of filters by the 10 | * [[Filters]] class. 11 | * 12 | * @param ec This class is needed to execute code asynchronously. 13 | * It is used below by the `map` method. 14 | */ 15 | @Singleton 16 | class ExampleFilter @Inject()(implicit ec: ExecutionContext) extends EssentialFilter { 17 | override def apply(next: EssentialAction) = EssentialAction { request => 18 | next(request).map { result => 19 | result.withHeaders("X-ExampleFilter" -> "foo") 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /app/controllers/HomeController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import javax.inject._ 4 | 5 | import play.api.mvc._ 6 | 7 | /** 8 | * This controller creates an `Action` to handle HTTP requests to the 9 | * application's home page. 10 | */ 11 | @Singleton 12 | class HomeController @Inject()(cc: ControllerComponents) (implicit assetsFinder: AssetsFinder) 13 | extends AbstractController(cc) { 14 | 15 | /** 16 | * Create an Action to render an HTML page with a welcome message. 17 | * The configuration in the `routes` file means that this method 18 | * will be called when the application receives a `GET` request with 19 | * a path of `/`. 20 | */ 21 | def index = Action { 22 | Ok(views.html.index("Your new application is ready.")) 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /app/controllers/CountController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import javax.inject._ 4 | 5 | import play.api.mvc._ 6 | import services.Counter 7 | 8 | /** 9 | * This controller demonstrates how to use dependency injection to 10 | * bind a component into a controller class. The class creates an 11 | * `Action` that shows an incrementing count to users. The [[Counter]] 12 | * object is injected by the Guice dependency injection system. 13 | */ 14 | @Singleton 15 | class CountController @Inject() (cc: ControllerComponents, 16 | counter: Counter) extends AbstractController(cc) { 17 | 18 | /** 19 | * Create an action that responds with the [[Counter]]'s current 20 | * count. The result is plain text. This `Action` is mapped to 21 | * `GET /count` requests by an entry in the `routes` config file. 22 | */ 23 | def count = Action { Ok(counter.nextCount().toString) } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: Merge PRs that are ready 3 | conditions: 4 | - status-success=Travis CI - Pull Request 5 | - status-success=typesafe-cla-validator 6 | - "#approved-reviews-by>=1" 7 | - "#review-requested=0" 8 | - "#changes-requested-reviews-by=0" 9 | - label!=status:block-merge 10 | actions: 11 | merge: 12 | method: squash 13 | strict: smart 14 | 15 | - name: Merge TemplateControl's PRs that are ready 16 | conditions: 17 | - status-success=Travis CI - Pull Request 18 | - "#review-requested=0" 19 | - "#changes-requested-reviews-by=0" 20 | - label!=status:block-merge 21 | - label=status:merge-when-green 22 | - label!=status:block-merge 23 | actions: 24 | merge: 25 | method: squash 26 | strict: smart 27 | 28 | - name: Delete the PR branch after merge 29 | conditions: 30 | - merged 31 | actions: 32 | delete_head_branch: {} 33 | -------------------------------------------------------------------------------- /app/services/Counter.scala: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import java.util.concurrent.atomic.AtomicInteger 4 | import javax.inject._ 5 | 6 | /** 7 | * This trait demonstrates how to create a component that is injected 8 | * into a controller. The trait represents a counter that returns a 9 | * incremented number each time it is called. 10 | */ 11 | trait Counter { 12 | def nextCount(): Int 13 | } 14 | 15 | /** 16 | * This class is a concrete implementation of the [[Counter]] trait. 17 | * It is configured for Guice dependency injection in the [[Module]] 18 | * class. 19 | * 20 | * This class has a `Singleton` annotation because we need to make 21 | * sure we only use one counter per application. Without this 22 | * annotation we would get a new instance every time a [[Counter]] is 23 | * injected. 24 | */ 25 | @Singleton 26 | class AtomicCounter extends Counter { 27 | private val atomicCounter = new AtomicInteger() 28 | override def nextCount(): Int = atomicCounter.getAndIncrement() 29 | } 30 | -------------------------------------------------------------------------------- /app/views/main.scala.html: -------------------------------------------------------------------------------- 1 | @* 2 | * This template is called from the `index` template. This template 3 | * handles the rendering of the page header and body tags. It takes 4 | * three arguments, a `String` for the title of the page and an `Html` 5 | * object to insert into the body of the page and an `AssetFinder` 6 | * to define to reverse route static assets. 7 | *@ 8 | @(title: String, assetsFinder: AssetsFinder)(content: Html) 9 | 10 | 11 | 12 | 13 | @* Here's where we render the page title `String`. *@ 14 | @title 15 | 16 | 17 | 18 | 19 | 20 | @* And here's where we render the `Html` object containing 21 | * the page content. *@ 22 | @content 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/Module.scala: -------------------------------------------------------------------------------- 1 | import com.google.inject.AbstractModule 2 | import java.time.Clock 3 | 4 | import services.{ApplicationTimer, AtomicCounter, Counter} 5 | 6 | /** 7 | * This class is a Guice module that tells Guice how to bind several 8 | * different types. This Guice module is created when the Play 9 | * application starts. 10 | 11 | * Play will automatically use any class called `Module` that is in 12 | * the root package. You can create modules in other locations by 13 | * adding `play.modules.enabled` settings to the `application.conf` 14 | * configuration file. 15 | */ 16 | class Module extends AbstractModule { 17 | 18 | override def configure() = { 19 | // Use the system clock as the default implementation of Clock 20 | bind(classOf[Clock]).toInstance(Clock.systemDefaultZone) 21 | // Ask Guice to create an instance of ApplicationTimer when the 22 | // application starts. 23 | bind(classOf[ApplicationTimer]).asEagerSingleton() 24 | // Set AtomicCounter as the implementation for Counter. 25 | bind(classOf[Counter]).to(classOf[AtomicCounter]) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: scala 2 | scala: 2.12.8 3 | script: $SCRIPT 4 | 5 | env: 6 | matrix: 7 | - SCRIPT=scripts/test-sbt TRAVIS_JDK=adopt@1.8.202-08 8 | - SCRIPT=scripts/test-sbt TRAVIS_JDK=adopt@1.11.0-2 9 | - SCRIPT=scripts/test-gradle TRAVIS_JDK=adopt@1.8.202-08 10 | - SCRIPT=scripts/test-gradle TRAVIS_JDK=adopt@1.11.0-2 11 | 12 | matrix: 13 | fast_finish: true 14 | allow_failures: 15 | - env: SCRIPT=scripts/test-gradle TRAVIS_JDK=adopt@1.8.202-08 # current gradle doesn't support play 2.7 16 | - env: SCRIPT=scripts/test-gradle TRAVIS_JDK=adopt@1.11.0-2 # current gradle doesn't support play 2.7 17 | - env: SCRIPT=scripts/test-sbt TRAVIS_JDK=adopt@1.11.0-2 # not fully supported but allows problem discovery 18 | 19 | before_install: curl -Ls https://git.io/jabba | bash && . ~/.jabba/jabba.sh 20 | install: jabba install "$TRAVIS_JDK" && jabba use "$_" && java -Xmx32m -version 21 | 22 | cache: 23 | directories: 24 | - "$HOME/.gradle/caches" 25 | - "$HOME/.ivy2/cache" 26 | - "$HOME/.jabba/jdk" 27 | - "$HOME/.sbt" 28 | 29 | before_cache: 30 | - find $HOME/.ivy2 -name "ivydata-*.properties" -delete 31 | - find $HOME/.sbt -name "*.lock" -delete 32 | -------------------------------------------------------------------------------- /test/FunctionalSpec.scala: -------------------------------------------------------------------------------- 1 | import org.scalatestplus.play.PlaySpec 2 | import org.scalatestplus.play.guice.GuiceOneAppPerSuite 3 | import play.api.http.Status 4 | import play.api.test.FakeRequest 5 | import play.api.test.Helpers._ 6 | 7 | /** 8 | * Functional tests start a Play application internally, available 9 | * as `app`. 10 | */ 11 | class FunctionalSpec extends PlaySpec with GuiceOneAppPerSuite { 12 | 13 | "Routes" should { 14 | 15 | "send 404 on a bad request" in { 16 | route(app, FakeRequest(GET, "/boum")).map(status(_)) mustBe Some(NOT_FOUND) 17 | } 18 | 19 | "send 200 on a good request" in { 20 | route(app, FakeRequest(GET, "/")).map(status(_)) mustBe Some(OK) 21 | } 22 | 23 | } 24 | 25 | "HomeController" should { 26 | 27 | "render the index page" in { 28 | val home = route(app, FakeRequest(GET, "/")).get 29 | 30 | status(home) mustBe Status.OK 31 | contentType(home) mustBe Some("text/html") 32 | contentAsString(home) must include ("Your new application is ready.") 33 | } 34 | 35 | } 36 | 37 | "CountController" should { 38 | 39 | "return an increasing count" in { 40 | contentAsString(route(app, FakeRequest(GET, "/count")).get) mustBe "0" 41 | contentAsString(route(app, FakeRequest(GET, "/count")).get) mustBe "1" 42 | contentAsString(route(app, FakeRequest(GET, "/count")).get) mustBe "2" 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/UnitSpec.scala: -------------------------------------------------------------------------------- 1 | import akka.actor.ActorSystem 2 | import controllers.{AsyncController, CountController} 3 | import org.scalatestplus.play._ 4 | import play.api.test.Helpers._ 5 | import play.api.test.FakeRequest 6 | import services.Counter 7 | 8 | /** 9 | * Unit tests can run without a full Play application. 10 | */ 11 | class UnitSpec extends PlaySpec { 12 | 13 | "CountController" should { 14 | 15 | "return a valid result with action" in { 16 | val counter: Counter = new Counter { 17 | override def nextCount(): Int = 49 18 | } 19 | val controller = new CountController(stubControllerComponents(), counter) 20 | val result = controller.count(FakeRequest()) 21 | contentAsString(result) must equal("49") 22 | } 23 | } 24 | 25 | "AsyncController" should { 26 | 27 | "return a valid result on action.async" in { 28 | // actor system will create threads that must be cleaned up even if test fails 29 | val actorSystem = ActorSystem("test") 30 | try { 31 | implicit val ec = actorSystem.dispatcher 32 | val controller = new AsyncController(stubControllerComponents(), actorSystem) 33 | val resultFuture = controller.message(FakeRequest()) 34 | contentAsString(resultFuture) must be("Hi!") 35 | } finally { 36 | // always shut down actor system at the end of the test. 37 | actorSystem.terminate() 38 | } 39 | } 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ${application.home:-.}/logs/application.log 8 | 9 | %date [%level] from %logger in %thread - %message%n%xException 10 | 11 | 12 | 13 | 14 | 15 | %coloredLevel %logger{15} - %message%n%xException{10} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/services/ApplicationTimer.scala: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import java.time.{Clock, Instant} 4 | import javax.inject._ 5 | import play.api.Logger 6 | import play.api.inject.ApplicationLifecycle 7 | import scala.concurrent.Future 8 | 9 | /** 10 | * This class demonstrates how to run code when the 11 | * application starts and stops. It starts a timer when the 12 | * application starts. When the application stops it prints out how 13 | * long the application was running for. 14 | * 15 | * This class is registered for Guice dependency injection in the 16 | * [[Module]] class. We want the class to start when the application 17 | * starts, so it is registered as an "eager singleton". See the code 18 | * in the [[Module]] class to see how this happens. 19 | * 20 | * This class needs to run code when the server stops. It uses the 21 | * application's [[ApplicationLifecycle]] to register a stop hook. 22 | */ 23 | @Singleton 24 | class ApplicationTimer @Inject() (clock: Clock, appLifecycle: ApplicationLifecycle) { 25 | 26 | private val logger = org.slf4j.LoggerFactory.getLogger(classOf[ApplicationTimer]) 27 | 28 | // This code is called when the application starts. 29 | private val start: Instant = clock.instant 30 | logger.info(s"ApplicationTimer demo: Starting application at $start.") 31 | 32 | // When the application starts, register a stop hook with the 33 | // ApplicationLifecycle object. The code inside the stop hook will 34 | // be run when the application stops. 35 | appLifecycle.addStopHook { () => 36 | val stop: Instant = clock.instant 37 | val runningTime: Long = stop.getEpochSecond - start.getEpochSecond 38 | logger.info(s"ApplicationTimer demo: Stopping application at ${clock.instant} after ${runningTime}s.") 39 | Future.successful(()) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/controllers/AsyncController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import javax.inject._ 4 | 5 | import akka.actor.ActorSystem 6 | import play.api.mvc._ 7 | 8 | import scala.concurrent.duration._ 9 | import scala.concurrent.{ExecutionContext, Future, Promise} 10 | 11 | /** 12 | * This controller creates an `Action` that demonstrates how to write 13 | * simple asynchronous code in a controller. It uses a timer to 14 | * asynchronously delay sending a response for 1 second. 15 | * 16 | * @param cc standard controller components 17 | * @param actorSystem We need the `ActorSystem`'s `Scheduler` to 18 | * run code after a delay. 19 | * @param exec We need an `ExecutionContext` to execute our 20 | * asynchronous code. When rendering content, you should use Play's 21 | * default execution context, which is dependency injected. If you are 22 | * using blocking operations, such as database or network access, then you should 23 | * use a different custom execution context that has a thread pool configured for 24 | * a blocking API. 25 | */ 26 | @Singleton 27 | class AsyncController @Inject()(cc: ControllerComponents, actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends AbstractController(cc) { 28 | 29 | /** 30 | * Creates an Action that returns a plain text message after a delay 31 | * of 1 second. 32 | * 33 | * The configuration in the `routes` file means that this method 34 | * will be called when the application receives a `GET` request with 35 | * a path of `/message`. 36 | */ 37 | def message = Action.async { 38 | getFutureMessage(1.second).map { msg => Ok(msg) } 39 | } 40 | 41 | private def getFutureMessage(delayTime: FiniteDuration): Future[String] = { 42 | val promise: Promise[String] = Promise[String]() 43 | actorSystem.scheduler.scheduleOnce(delayTime) { 44 | promise.success("Hi!") 45 | }(actorSystem.dispatcher) // run scheduled tasks using the actor system's dispatcher 46 | promise.future 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | # These settings are synced to GitHub by https://probot.github.io/apps/settings/ 2 | repository: 3 | homepage: "https://developer.lightbend.com/start/?group=play" 4 | topics: playframework, example, example-project, sample, sample-app, jvm, webapp 5 | private: false 6 | has_issues: true 7 | # We don't need projects in sample projects 8 | has_projects: false 9 | # We don't need wiki in sample projects 10 | has_wiki: false 11 | has_downloads: true 12 | default_branch: 2.7.x 13 | allow_squash_merge: true 14 | allow_merge_commit: false 15 | allow_rebase_merge: false 16 | 17 | teams: 18 | - name: core 19 | permission: admin 20 | - name: integrators 21 | permission: write 22 | - name: write-bots 23 | permission: write 24 | 25 | branches: 26 | - name: "[0-9].*.x" 27 | protection: 28 | # We don't require reviews for sample applications because they are mainly 29 | # updated by template-control, which is an automated process 30 | required_pull_request_reviews: null 31 | # Required. Require status checks to pass before merging. Set to null to disable 32 | required_status_checks: 33 | # Required. The list of status checks to require in order to merge into this branch 34 | contexts: ["Travis CI - Pull Request", "typesafe-cla-validator"] 35 | 36 | # Labels: tailored list of labels to be used by sample applications 37 | labels: 38 | - color: f9d0c4 39 | name: "closed:declined" 40 | - color: f9d0c4 41 | name: "closed:duplicated" 42 | oldname: duplicate 43 | - color: f9d0c4 44 | name: "closed:invalid" 45 | oldname: invalid 46 | - color: f9d0c4 47 | name: "closed:question" 48 | oldname: question 49 | - color: f9d0c4 50 | name: "closed:wontfix" 51 | oldname: wontfix 52 | - color: 7057ff 53 | name: "good first issue" 54 | - color: 7057ff 55 | name: "Hacktoberfest" 56 | - color: 7057ff 57 | name: "help wanted" 58 | - color: cceecc 59 | name: "status:backlog" 60 | oldname: backlog 61 | - color: b60205 62 | name: "status:block-merge" 63 | oldname: block-merge 64 | - color: b60205 65 | name: "status:blocked" 66 | - color: 0e8a16 67 | name: "status:in-progress" 68 | - color: 0e8a16 69 | name: "status:merge-when-green" 70 | oldname: merge-when-green 71 | - color: fbca04 72 | name: "status:needs-backport" 73 | - color: fbca04 74 | name: "status:needs-forwardport" 75 | - color: fbca04 76 | name: "status:needs-info" 77 | - color: fbca04 78 | name: "status:needs-verification" 79 | - color: 0e8a16 80 | name: "status:ready" 81 | - color: fbca04 82 | name: "status:to-review" 83 | oldname: review 84 | - color: c5def5 85 | name: "topic:build/tests" 86 | - color: c5def5 87 | name: "topic:dev-environment" 88 | - color: c5def5 89 | name: "topic:documentation" 90 | - color: c5def5 91 | name: "topic:jdk-next" 92 | - color: b60205 93 | name: "type:defect" 94 | oldname: bug 95 | - color: 0052cc 96 | name: "type:feature" 97 | - color: 0052cc 98 | name: "type:improvement" 99 | oldname: enhancement 100 | - color: 0052cc 101 | name: "type:updates" 102 | - color: bf0d92 103 | name: "type:template-control" 104 | oldname: template-control 105 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /app/views/welcome.scala.html: -------------------------------------------------------------------------------- 1 | @(message: String, style: String = "scala") 2 | 3 | @defining(play.core.PlayVersion.current) { version => 4 | 5 |
6 |
7 |

@message

8 |
9 |
10 | 11 |
12 |
13 | 14 |

Welcome to Play

15 | 16 |

17 | Congratulations, you’ve just created a new Play application. This page will help you with the next few steps. 18 |

19 | 20 |
21 |

22 | You’re using Play @version 23 |

24 |
25 | 26 |

Why do you see this page?

27 | 28 |

29 | The conf/routes file defines a route that tells Play to invoke the HomeController.index action 30 | whenever a browser requests the / URI using the GET method: 31 |

32 | 33 |
# Home page
 34 | GET     /               controllers.HomeController.index
35 | 36 |

37 | Play has invoked the controllers.HomeController.index method to obtain the Action to execute: 38 |

39 | 40 |
def index = Action {
 41 |   Ok(views.html.index("Your new application is ready."))
 42 | }
43 | 44 |

45 | An action is a function that handles the incoming HTTP request, and returns the HTTP result to send back to the web client. 46 | Here we send a 200 OK response, using a template to fill its content. 47 |

48 | 49 |

50 | The template is defined in the app/views/index.scala.html file and compiled as a Scala function. 51 |

52 | 53 |
@@(message: String)
 54 | 
 55 | @@main("Welcome to Play") {
 56 | 
 57 |     @@welcome(message, style = "scala")
 58 | 
 59 | }
60 | 61 |

62 | The first line of the template defines the function signature. Here it just takes a single String parameter. 63 | This template then calls another function defined in app/views/main.scala.html, which displays the HTML 64 | layout, and another function that displays this welcome message. You can freely add any HTML fragment mixed with Scala 65 | code in this file. 66 |

67 | 68 |

You can read more about Twirl, the template language used by Play, and how Play handles actions.

69 | 70 |

Async Controller

71 | 72 | Now that you've seen how Play renders a page, take a look at AsyncController.scala, which shows how to do asynchronous programming when handling a request. The code is almost exactly the same as HomeController.scala, but instead of returning Result, the action returns Future[String] to Play. When the execution completes, Play can use a thread to render the result without blocking the thread in the mean time. 73 | 74 |

75 | Click here for the AsyncController action! 76 |

77 | 78 |

79 | You can read more about asynchronous actions in the documentation. 80 |

81 | 82 |

Count Controller

83 | 84 |

85 | Both the HomeController and AsyncController are very simple, and typically controllers present the results of the interaction of several services. As an example, see the CountController, which shows how to inject a component into a controller and use the component when handling requests. The count controller increments every time you refresh the page, so keep refreshing to see the numbers go up. 86 |

87 | 88 |

89 | Click here for the CountController action! 90 |

91 | 92 |

93 | You can read more about dependency injection in the documentation. 94 |

95 | 96 |

Need more info on the console?

97 | 98 |

99 | For more information on the various commands you can run on Play, i.e. running tests and packaging applications for production, see Using the Play console. 100 |

101 | 102 |

Need to set up an IDE?

103 | 104 |

105 | You can start hacking your application right now using any text editor. Any changes will be automatically reloaded at each page refresh, 106 | including modifications made to Scala source files. 107 |

108 | 109 |

110 | If you want to set-up your application in IntelliJ IDEA or any other Java IDE, check the 111 | Setting up your preferred IDE page. 112 |

113 | 114 |

Need more documentation?

115 | 116 |

117 | Play documentation is available at https://www.playframework.com/documentation. 118 |

119 | 120 |

121 | Play comes with lots of example templates showcasing various bits of Play functionality at https://www.playframework.com/download#examples. 122 |

123 | 124 |

Need more help?

125 | 126 |

127 | Play questions are asked and answered on Stackoverflow using the "playframework" tag: https://stackoverflow.com/questions/tagged/playframework 128 |

129 | 130 |

131 | The Discuss Play Forum is where Play users come to seek help, 132 | announce projects, and discuss issues and new features. 133 |

134 | 135 |

136 | Gitter is a real time chat channel, like IRC. The playframework/playframework channel is used by Play users to discuss the ins and outs of writing great Play applications. 137 |

138 | 139 |
140 | 141 | 161 | 162 |
163 | } 164 | -------------------------------------------------------------------------------- /public/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009-2017 Lightbend Inc. 3 | */ 4 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;} 5 | table{border-collapse:collapse;border-spacing:0;} 6 | caption,th,td{text-align:left;font-weight:normal;} 7 | form legend{display:none;} 8 | blockquote:before,blockquote:after,q:before,q:after{content:"";} 9 | blockquote,q{quotes:"" "";} 10 | ol,ul{list-style:none;} 11 | hr{display:none;visibility:hidden;} 12 | :focus{outline:0;} 13 | article{}article h1,article h2,article h3,article h4,article h5,article h6{color:#333;font-weight:bold;line-height:1.25;margin-top:1.3em;} 14 | article h1 a,article h2 a,article h3 a,article h4 a,article h5 a,article h6 a{font-weight:inherit;color:#333;}article h1 a:hover,article h2 a:hover,article h3 a:hover,article h4 a:hover,article h5 a:hover,article h6 a:hover{color:#333;} 15 | article h1{font-size:36px;margin:0 0 18px;border-bottom:4px solid #eee;} 16 | article h2{font-size:25px;margin-bottom:9px;border-bottom:2px solid #eee;} 17 | article h3{font-size:18px;margin-bottom:9px;} 18 | article h4{font-size:15px;margin-bottom:3px;} 19 | article h5{font-size:12px;font-weight:normal;margin-bottom:3px;} 20 | article .subheader{color:#777;font-weight:300;margin-bottom:24px;} 21 | article p{line-height:1.3em;margin:1em 0;} 22 | article p img{margin:0;} 23 | article p.lead{font-size:18px;font-size:1.8rem;line-height:1.5;} 24 | article li>p:first-child{margin-top:0;} 25 | article li>p:last-child{margin-bottom:0;} 26 | article ul li,article ol li{position:relative;padding:4px 0 4px 14px;}article ul li ol,article ol li ol,article ul li ul,article ol li ul{margin-left:20px;} 27 | article ul li:before,article ol li:before{position:absolute;top:8px;left:0;content:"►";color:#ccc;font-size:10px;margin-right:5px;} 28 | article>ol{counter-reset:section;}article>ol li:before{color:#ccc;font-size:13px;} 29 | article>ol>li{padding:6px 0 4px 20px;counter-reset:chapter;}article>ol>li:before{content:counter(section) ".";counter-increment:section;} 30 | article>ol>li>ol>li{padding:6px 0 4px 30px;counter-reset:item;}article>ol>li>ol>li:before{content:counter(section) "." counter(chapter);counter-increment:chapter;} 31 | article>ol>li>ol>li>ol>li{padding:6px 0 4px 40px;}article>ol>li>ol>li>ol>li:before{content:counter(section) "." counter(chapter) "." counter(item);counter-increment:item;} 32 | article em,article i{font-style:italic;line-height:inherit;} 33 | article strong,article b{font-weight:bold;line-height:inherit;} 34 | article small{font-size:60%;line-height:inherit;} 35 | article h1 small,article h2 small,article h3 small,article h4 small,article h5 small{color:#777;} 36 | article hr{border:solid #ddd;border-width:1px 0 0;clear:both;margin:12px 0 18px;height:0;} 37 | article abbr,article acronym{text-transform:uppercase;font-size:90%;color:#222;border-bottom:1px solid #ddd;cursor:help;} 38 | article abbr{text-transform:none;} 39 | article img{max-width:100%;} 40 | article pre{margin:10px 0;border:1px solid #ddd;padding:10px;background:#fafafa;color:#666;overflow:auto;border-radius:5px;} 41 | article code{background:#fafafa;color:#666;font-family:inconsolata, monospace;border:1px solid #ddd;border-radius:3px;height:4px;padding:0;} 42 | article a code{color:#80c846;}article a code:hover{color:#6dae38;} 43 | article pre code{border:0;background:inherit;border-radius:0;line-height:inherit;font-size:14px;} 44 | article pre.prettyprint{border:1px solid #ddd;padding:10px;} 45 | article blockquote,article blockquote p,article p.note{line-height:20px;color:#4c4742;} 46 | article blockquote,article .note{margin:0 0 18px;padding:1px 20px;background:#fff7d6;}article blockquote li:before,article .note li:before{color:#e0bc6f;} 47 | article blockquote code,article .note code{background:#f5d899;border:none;color:inherit;} 48 | article blockquote a,article .note a{color:#6dae38;} 49 | article blockquote pre,article .note pre{background:#F5D899 !important;color:#48484C !important;border:none !important;} 50 | article p.note{padding:15px 20px;} 51 | article table{width:100%;}article table td{padding:8px;} 52 | article table tr{background:#F4F4F7;border-bottom:1px solid #eee;} 53 | article table tr:nth-of-type(odd){background:#fafafa;} 54 | article dl dt{font-weight:bold;} 55 | article dl.tabbed{position:relative;} 56 | article dl.tabbed dt{float:left;margin:0 5px 0 0;border:1px solid #ddd;padding:0 20px;line-height:2;border-radius: 5px 5px 0 0;} 57 | article dl.tabbed dt a{display:block;height:30px;color:#333;text-decoration:none;} 58 | article dl.tabbed dt.current{background: #f7f7f7;} 59 | article dl.tabbed dd{position:absolute;width:100%;left:0;top:30px;} 60 | article dl.tabbed dd pre{margin-top:0;border-top-left-radius:0;} 61 | a{color:#80c846;}a:hover{color:#6dae38;} 62 | p{margin:1em 0;} 63 | h1{-webkit-font-smoothing:antialiased;} 64 | h2{font-weight:bold;font-size:28px;} 65 | hr{clear:both;margin:20px 0 25px 0;border:none;border-top:1px solid #444;visibility:visible;display:block;} 66 | section{padding:50px 0;} 67 | body{background:#f5f5f5;background:#fff;color:#555;font:15px "Helvetica Nueue",sans-serif;padding:0px 0 0px;} 68 | .wrapper{width:960px;margin:0 auto;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;padding:60px 0;}.wrapper:after{content:" ";display:block;clear:both;} 69 | .wrapper article{min-height:310px;width:650px;float:left;} 70 | .wrapper aside{width:270px;float:right;}.wrapper aside ul{margin:2px 0 30px;}.wrapper aside ul a{display:block;padding:3px 0 3px 10px;margin:2px 0;border-left:4px solid #eee;}.wrapper aside ul a:hover{border-color:#80c846;} 71 | .wrapper aside h3{font-size:18px;color:#333;font-weight:bold;line-height:2em;margin:9px 0;border-bottom:1px solid #eee;} 72 | .wrapper aside.stick{position:fixed;right:50%;margin-right:-480px;top:120px;bottom:0;overflow:hidden;} 73 | .half{width:50%;float:left;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;} 74 | header{position:fixed;top:0;z-index:1000;width:100%;height:50px;line-height:50px;padding:30px 0;background:#fff;background:rgba(255, 255, 255, 0.95);border-bottom:1px solid #ccc;box-shadow:0 4px 0 rgba(0, 0, 0, 0.1);}header #logo{position:absolute;left:50%;margin-left:-480px;} 75 | header nav{position:absolute;right:50%;margin-right:-480px;}header nav a{padding:0 10px 4px;font-size:21px;font-weight:500;text-decoration:none;} 76 | header nav a.selected{border-bottom:3px solid #E9E9E9;} 77 | header nav a.download{position:relative;background:#80c846;color:white;margin-left:10px;padding:5px 10px 2px;font-weight:700;border-radius:5px;box-shadow:0 3px 0 #6dae38;text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.2);-webkit-transition:all 70ms ease-out;border:0;}header nav a.download:hover{box-shadow:0 3px 0 #6dae38,0 3px 4px rgba(0, 0, 0, 0.3);} 78 | header nav a.download:active{box-shadow:0 1px 0 #6dae38;top:2px;-webkit-transition:none;} 79 | #download,#getLogo{display:none;position:absolute;padding:5px 20px;width:200px;background:#000;background:rgba(0, 0, 0, 0.8);border-radius:5px;color:#999;line-height:15px;}#download a,#getLogo a{color:#ccc;text-decoration:none;}#download a:hover,#getLogo a:hover{color:#fff;} 80 | #getLogo{text-align:center;}#getLogo h3{font-size:16px;color:#80c846;margin:0 0 15px;} 81 | #getLogo figure{border-radius:3px;margin:5px 0;padding:5px;background:#fff;line-height:25px;width:80px;display:inline-block;}#getLogo figure a{color:#999;text-decoration:none;}#getLogo figure a:hover{color:#666;} 82 | #download{top:85px;right:50%;margin-right:-480px;}#download .button{font-size:16px;color:#80c846;} 83 | #getLogo{top:85px;left:50%;padding:20px;margin-left:-480px;}#getLogo ul{margin:5px 0;} 84 | #getLogo li{margin:1px 0;} 85 | #news{background:#f5f5f5;color:#999;font-size:17px;box-shadow:0 1px 0 rgba(0, 0, 0, 0.1);position:relative;z-index:2;padding:3px 0;}#news ul{box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;background:url(/assets/images/news.png) 10px center no-repeat;padding:19px 0 19px 60px;} 86 | #content{padding:30px 0;} 87 | #top{background:#80c846 url(/assets/images/header-pattern.png) fixed;box-shadow:0 -4px 0 rgba(0, 0, 0, 0.1) inset;padding:0;position:relative;}#top .wrapper{padding:30px 0;} 88 | #top h1{float:left;color:#fff;font-size:35px;line-height:48px;text-shadow:2px 2px 0 rgba(0, 0, 0, 0.1);}#top h1 a{text-decoration:none;color:#fff;} 89 | #top nav{float:right;margin-top:10px;line-height:25px;}#top nav .versions,#top nav form{float:left;margin:0 5px;} 90 | #top nav .versions{height:25px;display:inline-block;border:1px solid #6dae38;border-radius:3px;background:#80c846;background:-moz-linear-gradient(top, #80c846 0%, #6dae38 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #80c846), color-stop(100%, #6dae38));background:-webkit-linear-gradient(top, #80c846 0%, #6dae38 100%);background:-o-linear-gradient(top, #80c846 0%, #6dae38 100%);background:-ms-linear-gradient(top, #80c846 0%, #6dae38 100%);background:linear-gradient(top, #80c846 0%, #6dae38 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#80c846', endColorstr='#6dae38',GradientType=0 );box-shadow:inset 0 -1px 1px #80c846;text-align:center;color:#fff;text-shadow:-1px -1px 0 #6dae38;}#top nav .versions span{padding:0 4px;position:absolute;}#top nav .versions span:before{content:"⬍";color:rgba(0, 0, 0, 0.4);text-shadow:1px 1px 0 #80c846;margin-right:4px;} 91 | #top nav .versions select{opacity:0;position:relative;z-index:9;} 92 | #top .follow{display:inline-block;border:1px solid #6dae38;border-radius:3px;background:#80c846;background:-moz-linear-gradient(top, #80c846 0%, #6dae38 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #80c846), color-stop(100%, #6dae38));background:-webkit-linear-gradient(top, #80c846 0%, #6dae38 100%);background:-o-linear-gradient(top, #80c846 0%, #6dae38 100%);background:-ms-linear-gradient(top, #80c846 0%, #6dae38 100%);background:linear-gradient(top, #80c846 0%, #6dae38 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#80c846', endColorstr='#6dae38',GradientType=0 );box-shadow:inset 0 -1px 1px #80c846;text-align:center;vertical-align:middle;color:#fff;text-shadow:-1px -1px 0 #6dae38;padding:4px 8px;text-decoration:none;position:absolute;top:41px;left:50%;margin-left:210px;width:250px;}#top .follow:before{vertical-align:middle;content:url(/assets/images/twitter.png);margin-right:10px;} 93 | #top input{width:80px;-webkit-transition:width 200ms ease-in-out;-moz-transition:width 200ms ease-in-out;}#top input:focus{width:200px;} 94 | #title{width:500px;float:left;font-size:17px;color:#2d6201;} 95 | #quicklinks{width:350px;margin:-15px 0 0 0;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;float:right;padding:30px;background:#fff;color:#888;box-shadow:0 3px 5px rgba(0, 0, 0, 0.2);}#quicklinks h2{color:#80c846;font-size:20px;margin-top:15px;padding:10px 0 5px 0;border-top:1px solid #eee;}#quicklinks h2:first-child{margin:0;padding:0 0 5px 0;border:0;} 96 | #quicklinks p{margin:0;} 97 | #quicklinks a{color:#444;}#quicklinks a:hover{color:#222;} 98 | .tweet{border-bottom:1px solid #eee;padding:6px 0 20px 60px;position:relative;min-height:50px;margin-bottom:20px;}.tweet img{position:absolute;left:0;top:8px;} 99 | .tweet strong{font-size:14px;font-weight:bold;} 100 | .tweet span{font-size:12px;color:#888;} 101 | .tweet p{padding:0;margin:5px 0 0 0;} 102 | footer{padding:40px 0;background:#363736;background:#eee;border-top:1px solid #e5e5e5;color:#aaa;position:relative;}footer .logo{position:absolute;top:55px;left:50%;margin-left:-480px;-webkit-transform:translate3d(0, 0, 0);-moz-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);} 103 | footer:after{content:" ";display:block;clear:both;} 104 | footer .links{width:960px;margin:0 auto;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;margin:0 auto;padding-left:200px;}footer .links:after{content:" ";display:block;clear:both;} 105 | footer .links dl{width:33%;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;padding:0 10px;float:left;} 106 | footer .links dt{color:#80c846;font-weight:bold;} 107 | footer .links a{color:#aaa;text-decoration:none;}footer .links a:hover{color:#888;} 108 | footer .licence{width:960px;margin:0 auto;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;margin:20px auto 0;padding-top:20px;border-top:2px solid #ddd;font-size:12px;}footer .licence:after{content:" ";display:block;clear:both;} 109 | footer .licence .typesafe,footer .licence .zenexity{float:right;} 110 | footer .licence .typesafe{position:relative;top:-3px;margin-left:10px;} 111 | footer .licence a{color:#999;} 112 | div.coreteam{position:relative;min-height:80px;border-bottom:1px solid #eee;}div.coreteam img{width:50px;position:absolute;left:0;top:0;padding:2px;border:1px solid #ddd;} 113 | div.coreteam a{color:inherit;text-decoration:none;} 114 | div.coreteam h2{padding-left:70px;border:none;font-size:20px;} 115 | div.coreteam p{margin-top:5px;padding-left:70px;} 116 | ul.contributors{padding:0;margin:0;list-style:none;}ul.contributors li{padding:6px 0 !important;margin:0;}ul.contributors li:before{content:' ';} 117 | ul.contributors img{width:25px;padding:1px;border:1px solid #ddd;margin-right:5px;vertical-align:middle;} 118 | ul.contributors a{color:inherit;text-decoration:none;} 119 | ul.contributors span{font-weight:bold;color:#666;} 120 | ul.contributors.others li{display:inline-block;width:32.3333%;} 121 | div.list{float:left;width:33.3333%;margin-bottom:30px;} 122 | h2{clear:both;} 123 | span.by{font-size:14px;font-weight:normal;} 124 | form dl{padding:10px 0;} 125 | dd.info{color:#888;font-size:12px;} 126 | dd.error{color:#c00;} 127 | aside a[href^="http"]:after,.doc a[href^="http"]:after{content:url(/assets/images/external.png);vertical-align:middle;margin-left:5px;} 128 | -------------------------------------------------------------------------------- /conf/application.conf: -------------------------------------------------------------------------------- 1 | # This is the main configuration file for the application. 2 | # https://www.playframework.com/documentation/latest/ConfigFile 3 | # ~~~~~ 4 | # Play uses HOCON as its configuration file format. HOCON has a number 5 | # of advantages over other config formats, but there are two things that 6 | # can be used when modifying settings. 7 | # 8 | # You can include other configuration files in this main application.conf file: 9 | #include "extra-config.conf" 10 | # 11 | # You can declare variables and substitute for them: 12 | #mykey = ${some.value} 13 | # 14 | # And if an environment variable exists when there is no other substitution, then 15 | # HOCON will fall back to substituting environment variable: 16 | #mykey = ${JAVA_HOME} 17 | 18 | ## Akka 19 | # https://www.playframework.com/documentation/latest/ScalaAkka#Configuration 20 | # https://www.playframework.com/documentation/latest/JavaAkka#Configuration 21 | # ~~~~~ 22 | # Play uses Akka internally and exposes Akka Streams and actors in Websockets and 23 | # other streaming HTTP responses. 24 | akka { 25 | # "akka.log-config-on-start" is extraordinarly useful because it log the complete 26 | # configuration at INFO level, including defaults and overrides, so it s worth 27 | # putting at the very top. 28 | # 29 | # Put the following in your conf/logback.xml file: 30 | # 31 | # 32 | # 33 | # And then uncomment this line to debug the configuration. 34 | # 35 | #log-config-on-start = true 36 | } 37 | 38 | ## Secret key 39 | # http://www.playframework.com/documentation/latest/ApplicationSecret 40 | # ~~~~~ 41 | # The secret key is used to sign Play's session cookie. 42 | # This must be changed for production, but we don't recommend you change it in this file. 43 | play.http.secret.key = "changeme" 44 | 45 | ## Modules 46 | # https://www.playframework.com/documentation/latest/Modules 47 | # ~~~~~ 48 | # Control which modules are loaded when Play starts. Note that modules are 49 | # the replacement for "GlobalSettings", which are deprecated in 2.5.x. 50 | # Please see https://www.playframework.com/documentation/latest/GlobalSettings 51 | # for more information. 52 | # 53 | # You can also extend Play functionality by using one of the publically available 54 | # Play modules: https://playframework.com/documentation/latest/ModuleDirectory 55 | play.modules { 56 | # By default, Play will load any class called Module that is defined 57 | # in the root package (the "app" directory), or you can define them 58 | # explicitly below. 59 | # If there are any built-in modules that you want to enable, you can list them here. 60 | #enabled += my.application.Module 61 | 62 | # If there are any built-in modules that you want to disable, you can list them here. 63 | #disabled += "" 64 | } 65 | 66 | ## IDE 67 | # https://www.playframework.com/documentation/latest/IDE 68 | # ~~~~~ 69 | # Depending on your IDE, you can add a hyperlink for errors that will jump you 70 | # directly to the code location in the IDE in dev mode. The following line makes 71 | # use of the IntelliJ IDEA REST interface: 72 | #play.editor="http://localhost:63342/api/file/?file=%s&line=%s" 73 | 74 | ## Internationalisation 75 | # https://www.playframework.com/documentation/latest/JavaI18N 76 | # https://www.playframework.com/documentation/latest/ScalaI18N 77 | # ~~~~~ 78 | # Play comes with its own i18n settings, which allow the user's preferred language 79 | # to map through to internal messages, or allow the language to be stored in a cookie. 80 | play.i18n { 81 | # The application languages 82 | langs = [ "en" ] 83 | 84 | # Whether the language cookie should be secure or not 85 | #langCookieSecure = true 86 | 87 | # Whether the HTTP only attribute of the cookie should be set to true 88 | #langCookieHttpOnly = true 89 | } 90 | 91 | ## Play HTTP settings 92 | # ~~~~~ 93 | play.http { 94 | ## Router 95 | # https://www.playframework.com/documentation/latest/JavaRouting 96 | # https://www.playframework.com/documentation/latest/ScalaRouting 97 | # ~~~~~ 98 | # Define the Router object to use for this application. 99 | # This router will be looked up first when the application is starting up, 100 | # so make sure this is the entry point. 101 | # Furthermore, it's assumed your route file is named properly. 102 | # So for an application router like `my.application.Router`, 103 | # you may need to define a router file `conf/my.application.routes`. 104 | # Default to Routes in the root package (aka "apps" folder) (and conf/routes) 105 | #router = my.application.Router 106 | 107 | ## Action Creator 108 | # https://www.playframework.com/documentation/latest/JavaActionCreator 109 | # ~~~~~ 110 | #actionCreator = null 111 | 112 | ## ErrorHandler 113 | # https://www.playframework.com/documentation/latest/JavaRouting 114 | # https://www.playframework.com/documentation/latest/ScalaRouting 115 | # ~~~~~ 116 | # If null, will attempt to load a class called ErrorHandler in the root package, 117 | #errorHandler = null 118 | 119 | ## Session & Flash 120 | # https://www.playframework.com/documentation/latest/JavaSessionFlash 121 | # https://www.playframework.com/documentation/latest/ScalaSessionFlash 122 | # ~~~~~ 123 | session { 124 | # Sets the cookie to be sent only over HTTPS. 125 | #secure = true 126 | 127 | # Sets the cookie to be accessed only by the server. 128 | #httpOnly = true 129 | 130 | # Sets the max-age field of the cookie to 5 minutes. 131 | # NOTE: this only sets when the browser will discard the cookie. Play will consider any 132 | # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, 133 | # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. 134 | #maxAge = 300 135 | 136 | # Sets the domain on the session cookie. 137 | #domain = "example.com" 138 | } 139 | 140 | flash { 141 | # Sets the cookie to be sent only over HTTPS. 142 | #secure = true 143 | 144 | # Sets the cookie to be accessed only by the server. 145 | #httpOnly = true 146 | } 147 | } 148 | 149 | ## Netty Provider 150 | # https://www.playframework.com/documentation/latest/SettingsNetty 151 | # ~~~~~ 152 | play.server.netty { 153 | # Whether the Netty wire should be logged 154 | #log.wire = true 155 | 156 | # If you run Play on Linux, you can use Netty's native socket transport 157 | # for higher performance with less garbage. 158 | #transport = "native" 159 | } 160 | 161 | ## WS (HTTP Client) 162 | # https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS 163 | # ~~~~~ 164 | # The HTTP client primarily used for REST APIs. The default client can be 165 | # configured directly, but you can also create different client instances 166 | # with customized settings. You must enable this by adding to build.sbt: 167 | # 168 | # libraryDependencies += ws // or javaWs if using java 169 | # 170 | play.ws { 171 | # Sets HTTP requests not to follow 302 requests 172 | #followRedirects = false 173 | 174 | # Sets the maximum number of open HTTP connections for the client. 175 | #ahc.maxConnectionsTotal = 50 176 | 177 | ## WS SSL 178 | # https://www.playframework.com/documentation/latest/WsSSL 179 | # ~~~~~ 180 | ssl { 181 | # Configuring HTTPS with Play WS does not require programming. You can 182 | # set up both trustManager and keyManager for mutual authentication, and 183 | # turn on JSSE debugging in development with a reload. 184 | #debug.handshake = true 185 | #trustManager = { 186 | # stores = [ 187 | # { type = "JKS", path = "exampletrust.jks" } 188 | # ] 189 | #} 190 | } 191 | } 192 | 193 | ## Cache 194 | # https://www.playframework.com/documentation/latest/JavaCache 195 | # https://www.playframework.com/documentation/latest/ScalaCache 196 | # ~~~~~ 197 | # Play comes with an integrated cache API that can reduce the operational 198 | # overhead of repeated requests. You must enable this by adding to build.sbt: 199 | # 200 | # libraryDependencies += cache 201 | # 202 | play.cache { 203 | # If you want to bind several caches, you can bind the individually 204 | #bindCaches = ["db-cache", "user-cache", "session-cache"] 205 | } 206 | 207 | ## Filter Configuration 208 | # https://www.playframework.com/documentation/latest/Filters 209 | # ~~~~~ 210 | # There are a number of built-in filters that can be enabled and configured 211 | # to give Play greater security. 212 | # 213 | play.filters { 214 | 215 | # Enabled filters are run automatically against Play. 216 | # CSRFFilter, AllowedHostFilters, and SecurityHeadersFilters are enabled by default. 217 | enabled += filters.ExampleFilter 218 | 219 | # Disabled filters remove elements from the enabled list. 220 | #disabled += filters.ExampleFilters 221 | 222 | ## CORS filter configuration 223 | # https://www.playframework.com/documentation/latest/CorsFilter 224 | # ~~~~~ 225 | # CORS is a protocol that allows web applications to make requests from the browser 226 | # across different domains. 227 | # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has 228 | # dependencies on CORS settings. 229 | cors { 230 | # Filter paths by a whitelist of path prefixes 231 | #pathPrefixes = ["/some/path", ...] 232 | 233 | # The allowed origins. If null, all origins are allowed. 234 | #allowedOrigins = ["http://www.example.com"] 235 | 236 | # The allowed HTTP methods. If null, all methods are allowed 237 | #allowedHttpMethods = ["GET", "POST"] 238 | } 239 | 240 | ## CSRF Filter 241 | # https://www.playframework.com/documentation/latest/ScalaCsrf#Applying-a-global-CSRF-filter 242 | # https://www.playframework.com/documentation/latest/JavaCsrf#Applying-a-global-CSRF-filter 243 | # ~~~~~ 244 | # Play supports multiple methods for verifying that a request is not a CSRF request. 245 | # The primary mechanism is a CSRF token. This token gets placed either in the query string 246 | # or body of every form submitted, and also gets placed in the users session. 247 | # Play then verifies that both tokens are present and match. 248 | csrf { 249 | # Sets the cookie to be sent only over HTTPS 250 | #cookie.secure = true 251 | 252 | # Defaults to CSRFErrorHandler in the root package. 253 | #errorHandler = MyCSRFErrorHandler 254 | } 255 | 256 | ## Security headers filter configuration 257 | # https://www.playframework.com/documentation/latest/SecurityHeaders 258 | # ~~~~~ 259 | # Defines security headers that prevent XSS attacks. 260 | # If enabled, then all options are set to the below configuration by default: 261 | headers { 262 | # The X-Frame-Options header. If null, the header is not set. 263 | #frameOptions = "DENY" 264 | 265 | # The X-XSS-Protection header. If null, the header is not set. 266 | #xssProtection = "1; mode=block" 267 | 268 | # The X-Content-Type-Options header. If null, the header is not set. 269 | #contentTypeOptions = "nosniff" 270 | 271 | # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. 272 | #permittedCrossDomainPolicies = "master-only" 273 | 274 | # The Content-Security-Policy header. If null, the header is not set. 275 | #contentSecurityPolicy = "default-src 'self'" 276 | } 277 | 278 | ## Allowed hosts filter configuration 279 | # https://www.playframework.com/documentation/latest/AllowedHostsFilter 280 | # ~~~~~ 281 | # Play provides a filter that lets you configure which hosts can access your application. 282 | # This is useful to prevent cache poisoning attacks. 283 | hosts { 284 | # Allow requests to example.com, its subdomains, and localhost:9000. 285 | #allowed = [".example.com", "localhost:9000"] 286 | } 287 | } 288 | 289 | ## Evolutions 290 | # https://www.playframework.com/documentation/latest/Evolutions 291 | # ~~~~~ 292 | # Evolutions allows database scripts to be automatically run on startup in dev mode 293 | # for database migrations. You must enable this by adding to build.sbt: 294 | # 295 | # libraryDependencies += evolutions 296 | # 297 | play.evolutions { 298 | # You can disable evolutions for a specific datasource if necessary 299 | #db.default.enabled = false 300 | } 301 | 302 | ## Database Connection Pool 303 | # https://www.playframework.com/documentation/latest/SettingsJDBC 304 | # ~~~~~ 305 | # Play doesn't require a JDBC database to run, but you can easily enable one. 306 | # 307 | # libraryDependencies += jdbc 308 | # 309 | play.db { 310 | # The combination of these two settings results in "db.default" as the 311 | # default JDBC pool: 312 | #config = "db" 313 | #default = "default" 314 | 315 | # Play uses HikariCP as the default connection pool. You can override 316 | # settings by changing the prototype: 317 | prototype { 318 | # Sets a fixed JDBC connection pool size of 50 319 | #hikaricp.minimumIdle = 50 320 | #hikaricp.maximumPoolSize = 50 321 | } 322 | } 323 | 324 | ## JDBC Datasource 325 | # https://www.playframework.com/documentation/latest/JavaDatabase 326 | # https://www.playframework.com/documentation/latest/ScalaDatabase 327 | # ~~~~~ 328 | # Once JDBC datasource is set up, you can work with several different 329 | # database options: 330 | # 331 | # Slick (Scala preferred option): https://www.playframework.com/documentation/latest/PlaySlick 332 | # JPA (Java preferred option): https://playframework.com/documentation/latest/JavaJPA 333 | # EBean: https://playframework.com/documentation/latest/JavaEbean 334 | # Anorm: https://www.playframework.com/documentation/latest/ScalaAnorm 335 | # 336 | db { 337 | # You can declare as many datasources as you want. 338 | # By convention, the default datasource is named `default` 339 | 340 | # https://www.playframework.com/documentation/latest/Developing-with-the-H2-Database 341 | #default.driver = org.h2.Driver 342 | #default.url = "jdbc:h2:mem:play" 343 | #default.username = sa 344 | #default.password = "" 345 | 346 | # You can turn on SQL logging for any datasource 347 | # https://www.playframework.com/documentation/latest/Highlights25#Logging-SQL-statements 348 | #default.logSql=true 349 | } 350 | 351 | ## Static assets 352 | # Using configuration and assets finder 353 | # https://www.playframework.com/documentation/latest/AssetsOverview 354 | # Since 355 | play.assets { 356 | path = "/public" 357 | urlPrefix = "/assets" 358 | } 359 | --------------------------------------------------------------------------------