├── project ├── build.properties └── plugins.sbt ├── README.md ├── public ├── images │ ├── external.png │ ├── favicon.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 ├── app ├── services │ ├── Counter.java │ ├── AtomicCounter.java │ └── ApplicationTimer.java ├── views │ ├── index.scala.html │ ├── main.scala.html │ └── welcome.scala.html ├── controllers │ ├── HomeController.java │ ├── CountController.java │ └── AsyncController.java ├── filters │ └── ExampleFilter.java └── Module.java ├── conf ├── routes ├── logback.xml └── application.conf ├── test ├── FunctionalTest.java ├── BrowserTest.java └── UnitTest.java ├── .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 | -------------------------------------------------------------------------------- /public/images/external.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playframework/play-java-starter-example/2.7.x/public/images/external.png -------------------------------------------------------------------------------- /public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playframework/play-java-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 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playframework/play-java-starter-example/2.7.x/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /public/images/header-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/playframework/play-java-starter-example/2.7.x/public/images/header-pattern.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | target 3 | build 4 | /.idea 5 | /.idea_modules 6 | /.classpath 7 | /.project 8 | /.settings 9 | /.gradle 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 | -------------------------------------------------------------------------------- /app/services/Counter.java: -------------------------------------------------------------------------------- 1 | package services; 2 | 3 | /** 4 | * This interface demonstrates how to create a component that is injected 5 | * into a controller. The interface represents a counter that returns a 6 | * incremented number each time it is called. 7 | * 8 | * The {@link Modules} class binds this interface to the 9 | * {@link AtomicCounter} implementation. 10 | */ 11 | public interface Counter { 12 | int nextCount(); 13 | } 14 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | // The Play plugin 2 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0") 3 | 4 | // Play enhancer - this automatically generates getters/setters for public fields 5 | // and rewrites accessors of these fields to use the getters/setters. Remove this 6 | // plugin if you prefer not to have this feature, or disable on a per project 7 | // basis using disablePlugins(PlayEnhancer) in your build.sbt 8 | addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.2.2") 9 | 10 | -------------------------------------------------------------------------------- /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.7), 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 | -------------------------------------------------------------------------------- /app/views/index.scala.html: -------------------------------------------------------------------------------- 1 | @* 2 | * This template takes a single argument, a String containing a 3 | * message to display. 4 | *@ 5 | @(message: String) 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") { 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 = "java") 19 | 20 | } 21 | -------------------------------------------------------------------------------- /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(path="/public", file: Asset) 14 | -------------------------------------------------------------------------------- /app/controllers/HomeController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import play.mvc.*; 4 | 5 | import views.html.*; 6 | 7 | /** 8 | * This controller contains an action to handle HTTP requests 9 | * to the application's home page. 10 | */ 11 | public class HomeController extends Controller { 12 | 13 | /** 14 | * An action that renders an HTML page with a welcome message. 15 | * The configuration in the routes file means that 16 | * this method will be called when the application receives a 17 | * GET request with a path of /. 18 | */ 19 | public Result index() { 20 | return ok(index.render("Your new application is ready.")); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/services/AtomicCounter.java: -------------------------------------------------------------------------------- 1 | package services; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | import javax.inject.*; 5 | 6 | /** 7 | * This class is a concrete implementation of the {@link Counter} trait. 8 | * It is configured for Guice dependency injection in the {@link Module} 9 | * class. 10 | * 11 | * This class has a {@link Singleton} annotation because we need to make 12 | * sure we only use one counter per application. Without this 13 | * annotation we would get a new instance every time a {@link Counter} is 14 | * injected. 15 | */ 16 | @Singleton 17 | public class AtomicCounter implements Counter { 18 | 19 | private final AtomicInteger atomicCounter = new AtomicInteger(); 20 | 21 | @Override 22 | public int nextCount() { 23 | return atomicCounter.getAndIncrement(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /test/FunctionalTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.Test; 2 | import play.test.WithApplication; 3 | import play.twirl.api.Content; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | /** 8 | * A functional test starts a Play application for every test. 9 | * 10 | * https://www.playframework.com/documentation/latest/JavaFunctionalTest 11 | */ 12 | public class FunctionalTest extends WithApplication { 13 | 14 | @Test 15 | public void renderTemplate() { 16 | // If you are calling out to Assets, then you must instantiate an application 17 | // because it makes use of assets metadata that is configured from 18 | // the application. 19 | 20 | Content html = views.html.index.render("Your new application is ready."); 21 | assertThat("text/html").isEqualTo(html.contentType()); 22 | assertThat(html.body()).contains("Your new application is ready."); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/filters/ExampleFilter.java: -------------------------------------------------------------------------------- 1 | package filters; 2 | 3 | import play.mvc.EssentialAction; 4 | import play.mvc.EssentialFilter; 5 | 6 | import javax.inject.Inject; 7 | import javax.inject.Singleton; 8 | import java.util.concurrent.Executor; 9 | 10 | /** 11 | * This is a simple filter that adds a header to all requests. 12 | */ 13 | @Singleton 14 | public class ExampleFilter extends EssentialFilter { 15 | 16 | private final Executor exec; 17 | 18 | /** 19 | * @param exec This class is needed to execute code asynchronously. 20 | */ 21 | @Inject 22 | public ExampleFilter(Executor exec) { 23 | this.exec = exec; 24 | } 25 | 26 | @Override 27 | public EssentialAction apply(EssentialAction next) { 28 | return EssentialAction.of(request -> 29 | next.apply(request).map(result -> 30 | result.withHeader("X-ExampleFilter", "foo"), exec) 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/BrowserTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.Test; 2 | import play.Application; 3 | import play.test.Helpers; 4 | import play.test.TestBrowser; 5 | import play.test.WithBrowser; 6 | 7 | import static org.junit.Assert.assertTrue; 8 | import static play.test.Helpers.*; 9 | 10 | public class BrowserTest extends WithBrowser { 11 | 12 | protected Application provideApplication() { 13 | return fakeApplication(inMemoryDatabase()); 14 | } 15 | 16 | protected TestBrowser provideBrowser(int port) { 17 | return Helpers.testBrowser(port); 18 | } 19 | 20 | /** 21 | * add your integration test here 22 | * in this example we just check if the welcome page is being shown 23 | */ 24 | @Test 25 | public void test() { 26 | browser.goTo("http://localhost:" + play.api.test.Helpers.testServerPort()); 27 | assertTrue(browser.pageSource().contains("Your new application is ready.")); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /.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/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 | * two arguments, a `String` for the title of the page and an `Html` 5 | * object to insert into the body of the page. 6 | *@ 7 | @(title: String)(content: Html) 8 | 9 | 10 | 11 | 12 | @* Here's where we render the page title `String`. *@ 13 | @title 14 | 15 | 16 | 17 | 18 | 19 | @* And here's where we render the `Html` object containing 20 | * the page content. *@ 21 | @content 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/controllers/CountController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import play.mvc.Controller; 4 | import play.mvc.Result; 5 | import services.Counter; 6 | 7 | import javax.inject.Inject; 8 | import javax.inject.Singleton; 9 | 10 | /** 11 | * This controller demonstrates how to use dependency injection to 12 | * bind a component into a controller class. The class contains an 13 | * action that shows an incrementing count to users. The {@link Counter} 14 | * object is injected by the Guice dependency injection system. 15 | */ 16 | @Singleton 17 | public class CountController extends Controller { 18 | 19 | private final Counter counter; 20 | 21 | @Inject 22 | public CountController(Counter counter) { 23 | this.counter = counter; 24 | } 25 | 26 | /** 27 | * An action that responds with the {@link Counter}'s current 28 | * count. The result is plain text. This action is mapped to 29 | * GET requests with a path of /count 30 | * requests by an entry in the routes config file. 31 | */ 32 | public Result count() { 33 | return ok(Integer.toString(counter.nextCount())); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /app/Module.java: -------------------------------------------------------------------------------- 1 | import com.google.inject.AbstractModule; 2 | import java.time.Clock; 3 | 4 | import services.ApplicationTimer; 5 | import services.AtomicCounter; 6 | import services.Counter; 7 | 8 | /** 9 | * This class is a Guice module that tells Guice how to bind several 10 | * different types. This Guice module is created when the Play 11 | * application starts. 12 | * 13 | * Play will automatically use any class called `Module` that is in 14 | * the root package. You can create modules in other locations by 15 | * adding `play.modules.enabled` settings to the `application.conf` 16 | * configuration file. 17 | */ 18 | public class Module extends AbstractModule { 19 | 20 | @Override 21 | public void configure() { 22 | // Use the system clock as the default implementation of Clock 23 | bind(Clock.class).toInstance(Clock.systemDefaultZone()); 24 | // Ask Guice to create an instance of ApplicationTimer when the 25 | // application starts. 26 | bind(ApplicationTimer.class).asEagerSingleton(); 27 | // Set AtomicCounter as the implementation for Counter. 28 | bind(Counter.class).to(AtomicCounter.class); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/UnitTest.java: -------------------------------------------------------------------------------- 1 | import akka.actor.ActorSystem; 2 | import controllers.AsyncController; 3 | import controllers.CountController; 4 | import org.junit.Test; 5 | import play.mvc.Result; 6 | import scala.concurrent.ExecutionContextExecutor; 7 | 8 | import java.util.concurrent.CompletionStage; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | import static org.awaitility.Awaitility.await; 12 | import static play.test.Helpers.contentAsString; 13 | 14 | /** 15 | * Unit testing does not require Play application start up. 16 | * 17 | * https://www.playframework.com/documentation/latest/JavaTest 18 | */ 19 | public class UnitTest { 20 | 21 | @Test 22 | public void simpleCheck() { 23 | int a = 1 + 1; 24 | assertThat(a).isEqualTo(2); 25 | } 26 | 27 | // Unit test a controller 28 | @Test 29 | public void testCount() { 30 | final CountController controller = new CountController(() -> 49); 31 | Result result = controller.count(); 32 | assertThat(contentAsString(result)).isEqualTo("49"); 33 | } 34 | 35 | // Unit test a controller with async return 36 | @Test 37 | public void testAsync() { 38 | final ActorSystem actorSystem = ActorSystem.create("test"); 39 | try { 40 | final ExecutionContextExecutor ec = actorSystem.dispatcher(); 41 | final AsyncController controller = new AsyncController(actorSystem, ec); 42 | final CompletionStage future = controller.message(); 43 | 44 | // Block until the result is completed 45 | await().untilAsserted(() -> 46 | assertThat(future.toCompletableFuture()) 47 | .isCompletedWithValueMatching(result -> contentAsString(result).equals("Hi!")) 48 | ); 49 | } finally { 50 | actorSystem.terminate(); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /app/services/ApplicationTimer.java: -------------------------------------------------------------------------------- 1 | package services; 2 | 3 | import java.time.Clock; 4 | import java.time.Instant; 5 | import java.util.concurrent.CompletableFuture; 6 | import javax.inject.*; 7 | import play.inject.ApplicationLifecycle; 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 | * {@link 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 {@link 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 {@link ApplicationLifecycle} to register a stop hook. 22 | */ 23 | @Singleton 24 | public class ApplicationTimer { 25 | 26 | private final Clock clock; 27 | private final ApplicationLifecycle appLifecycle; 28 | private final Instant start; 29 | 30 | private final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger("application"); 31 | 32 | @Inject 33 | public ApplicationTimer(Clock clock, ApplicationLifecycle appLifecycle) { 34 | this.clock = clock; 35 | this.appLifecycle = appLifecycle; 36 | // This code is called when the application starts. 37 | start = clock.instant(); 38 | logger.info("ApplicationTimer demo: Starting application at " + start); 39 | 40 | // When the application starts, register a stop hook with the 41 | // ApplicationLifecycle object. The code inside the stop hook will 42 | // be run when the application stops. 43 | appLifecycle.addStopHook(() -> { 44 | Instant stop = clock.instant(); 45 | Long runningTime = stop.getEpochSecond() - start.getEpochSecond(); 46 | logger.info("ApplicationTimer demo: Stopping application at " + clock.instant() + " after " + runningTime + "s."); 47 | return CompletableFuture.completedFuture(null); 48 | }); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/controllers/AsyncController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import akka.actor.ActorSystem; 4 | import javax.inject.*; 5 | 6 | import akka.actor.Scheduler; 7 | import play.*; 8 | import play.mvc.*; 9 | import java.util.concurrent.Executor; 10 | import java.util.concurrent.CompletableFuture; 11 | import java.util.concurrent.CompletionStage; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | import scala.concurrent.ExecutionContext; 15 | import scala.concurrent.duration.Duration; 16 | import scala.concurrent.ExecutionContextExecutor; 17 | 18 | /** 19 | * This controller contains an action that demonstrates how to write 20 | * simple asynchronous code in a controller. It uses a timer to 21 | * asynchronously delay sending a response for 1 second. 22 | */ 23 | @Singleton 24 | public class AsyncController extends Controller { 25 | 26 | private final ActorSystem actorSystem; 27 | private final ExecutionContextExecutor exec; 28 | 29 | /** 30 | * @param actorSystem We need the {@link ActorSystem}'s 31 | * {@link Scheduler} to run code after a delay. 32 | * @param exec We need a Java {@link Executor} to apply the result 33 | * of the {@link CompletableFuture} and a Scala 34 | * {@link ExecutionContext} so we can use the Akka {@link Scheduler}. 35 | * An {@link ExecutionContextExecutor} implements both interfaces. 36 | */ 37 | @Inject 38 | public AsyncController(ActorSystem actorSystem, ExecutionContextExecutor exec) { 39 | this.actorSystem = actorSystem; 40 | this.exec = exec; 41 | } 42 | 43 | /** 44 | * An action that returns a plain text message after a delay 45 | * of 1 second. 46 | * 47 | * The configuration in the routes file means that this method 48 | * will be called when the application receives a GET request with 49 | * a path of /message. 50 | */ 51 | public CompletionStage message() { 52 | return getFutureMessage(1, TimeUnit.SECONDS).thenApplyAsync(Results::ok, exec); 53 | } 54 | 55 | private CompletionStage getFutureMessage(long time, TimeUnit timeUnit) { 56 | CompletableFuture future = new CompletableFuture<>(); 57 | actorSystem.scheduler().scheduleOnce( 58 | Duration.create(time, timeUnit), 59 | () -> future.complete("Hi!"), 60 | exec 61 | ); 62 | return future; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /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 = "java") 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 |

38 | Play has invoked the controllers.HomeController.index method: 39 |

40 | 41 |
public Result index() {
 42 |     return ok(index.render("Your new application is ready."));
 43 | }
44 | 45 |

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

49 | 50 |

51 | The template is defined in the app/views/index.scala.html file and compiled as a standard Java class. 52 |

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

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

67 | 68 |
69 |

70 | Note that Scala is fully compatible with Java, so if you don’t know Scala don’t panic, a Scala statement is very similar to a Java one. 71 |

72 |
73 | 74 |

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

75 | 76 |

Async Controller

77 | 78 | Now that you've seen how Play renders a page, take a look at AsyncController.java, which shows how to do asynchronous programming when handling a request. The code is almost exactly the same as HomeController.java, but instead of returning Result, the action returns CompletionStage<Result> to Play. When the execution completes, Play can use a thread to render the result without blocking the thread in the mean time. 79 | 80 |

81 | Click here for the AsyncController action! 82 |

83 | 84 |

85 | You can read more about asynchronous actions in the documentation. 86 |

87 | 88 |

Count Controller

89 | 90 |

91 | 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. 92 |

93 | 94 |

95 | Click here for the CountController action! 96 |

97 | 98 |

99 | You can read more about dependency injection in the documentation. 100 |

101 | 102 |

Need more info on the console?

103 | 104 |

105 | 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. 106 |

107 | 108 |

Need to set up an IDE?

109 | 110 |

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

114 | 115 |

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

119 | 120 |

Need more documentation?

121 | 122 |

123 | Play documentation is available at https://www.playframework.com/documentation. 124 |

125 | 126 |

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

129 | 130 |

Need more help?

131 | 132 |

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

135 | 136 |

137 | The Discuss Play Forum is where Play users come to seek help, 138 | announce projects, and discuss issues and new features. 139 |

140 | 141 |

142 | 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. 143 |

144 | 145 |
146 | 147 | 167 | 168 |
169 | } 170 | -------------------------------------------------------------------------------- /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 subsitution, 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.ExampleFilter 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 localhost on ports 9000 (dev) and 19001 (default test) ports 285 | allowed = ["localhost:9000", "localhost:19001"] 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 | --------------------------------------------------------------------------------