diff --git a/play-framework/introduction/.gitignore b/play-framework/introduction/.gitignore
index eb372fc719..e497f3fc67 100644
--- a/play-framework/introduction/.gitignore
+++ b/play-framework/introduction/.gitignore
@@ -1,6 +1,7 @@
logs
target
/.idea
+/.g8
/.idea_modules
/.classpath
/.project
diff --git a/play-framework/introduction/LICENSE b/play-framework/introduction/LICENSE
deleted file mode 100644
index 4baedcb95f..0000000000
--- a/play-framework/introduction/LICENSE
+++ /dev/null
@@ -1,8 +0,0 @@
-This software is licensed under the Apache 2 license, quoted below.
-
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with
-the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
-
-Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
-language governing permissions and limitations under the License.
\ No newline at end of file
diff --git a/play-framework/introduction/README b/play-framework/introduction/README
deleted file mode 100644
index f21d092edf..0000000000
--- a/play-framework/introduction/README
+++ /dev/null
@@ -1,49 +0,0 @@
-This is your new Play application
-=================================
-
-This file will be packaged with your application when using `activator dist`.
-
-There are several demonstration files available in this template.
-
-Controllers
-===========
-
-- HomeController.java:
-
- Shows how to handle simple HTTP requests.
-
-- AsyncController.java:
-
- Shows how to do asynchronous programming when handling a request.
-
-- CountController.java:
-
- Shows how to inject a component into a controller and use the component when
- handling requests.
-
-Components
-==========
-
-- Module.java:
-
- Shows how to use Guice to bind all the components needed by your application.
-
-- Counter.java:
-
- An example of a component that contains state, in this case a simple counter.
-
-- ApplicationTimer.java:
-
- An example of a component that starts when the application starts and stops
- when the application stops.
-
-Filters
-=======
-
-- Filters.java:
-
- Creates the list of HTTP filters used by your application.
-
-- ExampleFilter.java
-
- A simple filter that adds a header to every response.
\ No newline at end of file
diff --git a/play-framework/introduction/app/Filters.java b/play-framework/introduction/app/Filters.java
deleted file mode 100644
index 255de8ca93..0000000000
--- a/play-framework/introduction/app/Filters.java
+++ /dev/null
@@ -1,46 +0,0 @@
-import javax.inject.*;
-import play.*;
-import play.mvc.EssentialFilter;
-import play.http.HttpFilters;
-import play.mvc.*;
-
-import filters.ExampleFilter;
-
-/**
- * This class configures filters that run on every request. This
- * class is queried by Play to get a list of filters.
- *
- * Play will automatically use filters from any class called
- * Filters that is placed the root package. You can load filters
- * from a different class by adding a `play.http.filters` setting to
- * the application.conf configuration file.
- */
-@Singleton
-public class Filters implements HttpFilters {
-
- private final Environment env;
- private final EssentialFilter exampleFilter;
-
- /**
- * @param env Basic environment settings for the current application.
- * @param exampleFilter A demonstration filter that adds a header to
- */
- @Inject
- public Filters(Environment env, ExampleFilter exampleFilter) {
- this.env = env;
- this.exampleFilter = exampleFilter;
- }
-
- @Override
- public EssentialFilter[] filters() {
- // Use the example filter if we're running development mode. If
- // we're running in production or test mode then don't use any
- // filters at all.
- if (env.mode().equals(Mode.DEV)) {
- return new EssentialFilter[] { exampleFilter };
- } else {
- return new EssentialFilter[] {};
- }
- }
-
-}
diff --git a/play-framework/introduction/app/Module.java b/play-framework/introduction/app/Module.java
deleted file mode 100644
index 6e7d1766ef..0000000000
--- a/play-framework/introduction/app/Module.java
+++ /dev/null
@@ -1,31 +0,0 @@
-import com.google.inject.AbstractModule;
-import java.time.Clock;
-
-import services.ApplicationTimer;
-import services.AtomicCounter;
-import services.Counter;
-
-/**
- * This class is a Guice module that tells Guice how to bind several
- * different types. This Guice module is created when the Play
- * application starts.
- *
- * Play will automatically use any class called `Module` that is in
- * the root package. You can create modules in other locations by
- * adding `play.modules.enabled` settings to the `application.conf`
- * configuration file.
- */
-public class Module extends AbstractModule {
-
- @Override
- public void configure() {
- // Use the system clock as the default implementation of Clock
- bind(Clock.class).toInstance(Clock.systemDefaultZone());
- // Ask Guice to create an instance of ApplicationTimer when the
- // application starts.
- bind(ApplicationTimer.class).asEagerSingleton();
- // Set AtomicCounter as the implementation for Counter.
- bind(Counter.class).to(AtomicCounter.class);
- }
-
-}
diff --git a/play-framework/introduction/app/controllers/AsyncController.java b/play-framework/introduction/app/controllers/AsyncController.java
deleted file mode 100644
index 92c84bb755..0000000000
--- a/play-framework/introduction/app/controllers/AsyncController.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package controllers;
-
-import akka.actor.ActorSystem;
-
-import javax.inject.*;
-
-import play.*;
-import play.mvc.*;
-
-import java.util.concurrent.Executor;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.TimeUnit;
-
-import scala.concurrent.duration.Duration;
-import scala.concurrent.ExecutionContextExecutor;
-
-/**
- * This controller contains an action that demonstrates how to write
- * simple asynchronous code in a controller. It uses a timer to
- * asynchronously delay sending a response for 1 second.
- *
- * @param actorSystem We need the {@link ActorSystem}'s
- * {@link Scheduler} to run code after a delay.
- * @param exec We need a Java {@link Executor} to apply the result
- * of the {@link CompletableFuture} and a Scala
- * {@link ExecutionContext} so we can use the Akka {@link Scheduler}.
- * An {@link ExecutionContextExecutor} implements both interfaces.
- */
-@Singleton
-public class AsyncController extends Controller {
-
- private final ActorSystem actorSystem;
- private final ExecutionContextExecutor exec;
-
- @Inject
- public AsyncController(ActorSystem actorSystem, ExecutionContextExecutor exec) {
- this.actorSystem = actorSystem;
- this.exec = exec;
- }
-
- /**
- * An action that returns a plain text message after a delay
- * of 1 second.
- *
- * The configuration in the routes file means that this method
- * will be called when the application receives a GET request with
- * a path of /message.
- */
- public CompletionStage message() {
- return getFutureMessage(1, TimeUnit.SECONDS).thenApplyAsync(Results::ok, exec);
- }
-
- private CompletionStage getFutureMessage(long time, TimeUnit timeUnit) {
- CompletableFuture future = new CompletableFuture<>();
- actorSystem.scheduler().scheduleOnce(
- Duration.create(time, timeUnit),
- () -> future.complete("Hi!"),
- exec
- );
- return future;
- }
-
-}
diff --git a/play-framework/introduction/app/controllers/CountController.java b/play-framework/introduction/app/controllers/CountController.java
deleted file mode 100644
index 02fcb15f8e..0000000000
--- a/play-framework/introduction/app/controllers/CountController.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package controllers;
-
-import javax.inject.*;
-import play.*;
-import play.mvc.*;
-
-import services.Counter;
-
-/**
- * This controller demonstrates how to use dependency injection to
- * bind a component into a controller class. The class contains an
- * action that shows an incrementing count to users. The {@link Counter}
- * object is injected by the Guice dependency injection system.
- */
-@Singleton
-public class CountController extends Controller {
-
- private final Counter counter;
-
- @Inject
- public CountController(Counter counter) {
- this.counter = counter;
- }
-
- /**
- * An action that responds with the {@link Counter}'s current
- * count. The result is plain text. This action is mapped to
- * GET requests with a path of /count
- * requests by an entry in the routes config file.
- */
- public Result count() {
- return ok(Integer.toString(counter.nextCount()));
- }
-
-}
diff --git a/play-framework/introduction/app/controllers/HomeController.java b/play-framework/introduction/app/controllers/HomeController.java
index 6a79856eb4..9b1146886e 100644
--- a/play-framework/introduction/app/controllers/HomeController.java
+++ b/play-framework/introduction/app/controllers/HomeController.java
@@ -1,14 +1,25 @@
package controllers;
+import play.libs.concurrent.HttpExecutionContext;
import play.mvc.*;
+import play.twirl.api.Html;
-import views.html.*;
+import javax.inject.Inject;
+import java.util.concurrent.CompletionStage;
+
+import static java.util.concurrent.CompletableFuture.supplyAsync;
/**
* This controller contains an action to handle HTTP requests
* to the application's home page.
*/
public class HomeController extends Controller {
+ private HttpExecutionContext ec;
+
+ @Inject
+ public HomeController(HttpExecutionContext ec) {
+ this.ec = ec;
+ }
/**
* An action that renders an HTML page with a welcome message.
@@ -17,7 +28,41 @@ public class HomeController extends Controller {
* GET request with a path of /.
*/
public Result index() {
- return ok(index.render("Your new application is ready."));
+ return ok(views.html.index.render());
}
+ public Result applyHtml() {
+ return ok(Html.apply("
This text will appear as a heading 1
"));
+ }
+
+ public Result badRequestPage() {
+ return badRequest("Your request data has issues.");
+ }
+
+ public Result notFoundPage() {
+ return notFound("Could not find the page you requested.");
+ }
+
+ public Result customContentType() {
+ return ok("This is some text content").as("text/html");
+ }
+
+ public CompletionStage asyncOperation() {
+ return supplyAsync(() -> {
+ return longRunningTask();
+ }, ec.current())
+ .thenApplyAsync(s -> {
+ return ok("Got result -> " + s);
+ }, ec.current());
+ }
+
+ private String longRunningTask() {
+ return "Long running task has completed";
+ }
+
+ public Result setHeaders() {
+ return ok("This is some text content")
+ .as("text/html")
+ .withHeader("Header-Key", "Some value");
+ }
}
diff --git a/play-framework/introduction/app/controllers/StudentController.java b/play-framework/introduction/app/controllers/StudentController.java
deleted file mode 100644
index 8b759b9598..0000000000
--- a/play-framework/introduction/app/controllers/StudentController.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package controllers;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import models.Student;
-import models.StudentStore;
-import play.libs.Json;
-import play.mvc.Controller;
-import play.mvc.Result;
-import util.Util;
-
-import java.util.Set;
-
-public class StudentController extends Controller {
- public Result create() {
- JsonNode json = request().body().asJson();
- if (json == null) {
- return badRequest(Util.createResponse("Expecting Json data", false));
- }
- Student student = StudentStore.getInstance().addStudent(Json.fromJson(json, Student.class));
- JsonNode jsonObject = Json.toJson(student);
- return created(Util.createResponse(jsonObject, true));
- }
-
- public Result update() {
- JsonNode json = request().body().asJson();
- if (json == null) {
- return badRequest(Util.createResponse("Expecting Json data", false));
- }
- Student student = StudentStore.getInstance().updateStudent(Json.fromJson(json, Student.class));
- if (student == null) {
- return notFound(Util.createResponse("Student not found", false));
- }
-
- JsonNode jsonObject = Json.toJson(student);
- return ok(Util.createResponse(jsonObject, true));
- }
-
- public Result retrieve(int id) {
- if (StudentStore.getInstance().getStudent(id) == null) {
- return notFound(Util.createResponse("Student with id:" + id + " not found", false));
- }
- JsonNode jsonObjects = Json.toJson(StudentStore.getInstance().getStudent(id));
- return ok(Util.createResponse(jsonObjects, true));
- }
-
- public Result listStudents() {
- Set result = StudentStore.getInstance().getAllStudents();
- ObjectMapper mapper = new ObjectMapper();
-
- JsonNode jsonData = mapper.convertValue(result, JsonNode.class);
- return ok(Util.createResponse(jsonData, true));
-
- }
-
- public Result delete(int id) {
- if (!StudentStore.getInstance().deleteStudent(id)) {
- return notFound(Util.createResponse("Student with id:" + id + " not found", false));
- }
- return ok(Util.createResponse("Student with id:" + id + " deleted", true));
- }
-
-}
diff --git a/play-framework/introduction/app/filters/ExampleFilter.java b/play-framework/introduction/app/filters/ExampleFilter.java
deleted file mode 100644
index 67a6a36cc3..0000000000
--- a/play-framework/introduction/app/filters/ExampleFilter.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package filters;
-
-import akka.stream.Materializer;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.Executor;
-import java.util.function.Function;
-import javax.inject.*;
-import play.mvc.*;
-import play.mvc.Http.RequestHeader;
-
-
-/**
- * This is a simple filter that adds a header to all requests. It's
- * added to the application's list of filters by the
- * {@link Filters} class.
- */
-@Singleton
-public class ExampleFilter extends Filter {
-
- private final Executor exec;
-
- /**
- * @param mat This object is needed to handle streaming of requests
- * and responses.
- * @param exec This class is needed to execute code asynchronously.
- * It is used below by the thenAsyncApply method.
- */
- @Inject
- public ExampleFilter(Materializer mat, Executor exec) {
- super(mat);
- this.exec = exec;
- }
-
- @Override
- public CompletionStage apply(
- Function> next,
- RequestHeader requestHeader) {
-
- return next.apply(requestHeader).thenApplyAsync(
- result -> result.withHeader("X-ExampleFilter", "foo"),
- exec
- );
- }
-
-}
diff --git a/play-framework/introduction/app/models/StudentStore.java b/play-framework/introduction/app/models/StudentStore.java
deleted file mode 100644
index add6a5dbd6..0000000000
--- a/play-framework/introduction/app/models/StudentStore.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package models;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class StudentStore {
- private static StudentStore instance;
- private Map students = new HashMap<>();
-
- public static StudentStore getInstance() {
- if (instance == null) {
- instance = new StudentStore();
- }
- return instance;
- }
-
- public Student addStudent(Student student) {
- int id = students.size();
- student.setId(id);
- students.put(id, student);
- return student;
- }
-
- public Student getStudent(int id) {
- return students.get(id);
- }
-
- public Set getAllStudents() {
- return new HashSet<>(students.values());
- }
-
- public Student updateStudent(Student student) {
- int id = student.getId();
- if (students.containsKey(id)) {
- students.put(id, student);
- return student;
- }
- return null;
- }
-
- public boolean deleteStudent(int id) {
- return students.remove(id) != null;
- }
-}
\ No newline at end of file
diff --git a/play-framework/introduction/app/services/ApplicationTimer.java b/play-framework/introduction/app/services/ApplicationTimer.java
deleted file mode 100644
index a951562b1d..0000000000
--- a/play-framework/introduction/app/services/ApplicationTimer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package services;
-
-import java.time.Clock;
-import java.time.Instant;
-import java.util.concurrent.CompletableFuture;
-import javax.inject.*;
-import play.Logger;
-import play.inject.ApplicationLifecycle;
-
-/**
- * This class demonstrates how to run code when the
- * application starts and stops. It starts a timer when the
- * application starts. When the application stops it prints out how
- * long the application was running for.
- *
- * This class is registered for Guice dependency injection in the
- * {@link Module} class. We want the class to start when the application
- * starts, so it is registered as an "eager singleton". See the code
- * in the {@link Module} class to see how this happens.
- *
- * This class needs to run code when the server stops. It uses the
- * application's {@link ApplicationLifecycle} to register a stop hook.
- */
-@Singleton
-public class ApplicationTimer {
-
- private final Clock clock;
- private final ApplicationLifecycle appLifecycle;
- private final Instant start;
-
- @Inject
- public ApplicationTimer(Clock clock, ApplicationLifecycle appLifecycle) {
- this.clock = clock;
- this.appLifecycle = appLifecycle;
- // This code is called when the application starts.
- start = clock.instant();
- Logger.info("ApplicationTimer demo: Starting application at " + start);
-
- // When the application starts, register a stop hook with the
- // ApplicationLifecycle object. The code inside the stop hook will
- // be run when the application stops.
- appLifecycle.addStopHook(() -> {
- Instant stop = clock.instant();
- Long runningTime = stop.getEpochSecond() - start.getEpochSecond();
- Logger.info("ApplicationTimer demo: Stopping application at " + clock.instant() + " after " + runningTime + "s.");
- return CompletableFuture.completedFuture(null);
- });
- }
-
-}
diff --git a/play-framework/introduction/app/services/AtomicCounter.java b/play-framework/introduction/app/services/AtomicCounter.java
deleted file mode 100644
index 41f741cbf7..0000000000
--- a/play-framework/introduction/app/services/AtomicCounter.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package services;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.inject.*;
-
-/**
- * This class is a concrete implementation of the {@link Counter} trait.
- * It is configured for Guice dependency injection in the {@link Module}
- * class.
- *
- * This class has a {@link Singleton} annotation because we need to make
- * sure we only use one counter per application. Without this
- * annotation we would get a new instance every time a {@link Counter} is
- * injected.
- */
-@Singleton
-public class AtomicCounter implements Counter {
-
- private final AtomicInteger atomicCounter = new AtomicInteger();
-
- @Override
- public int nextCount() {
- return atomicCounter.getAndIncrement();
- }
-
-}
diff --git a/play-framework/introduction/app/services/Counter.java b/play-framework/introduction/app/services/Counter.java
deleted file mode 100644
index dadad8b09d..0000000000
--- a/play-framework/introduction/app/services/Counter.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package services;
-
-/**
- * This interface demonstrates how to create a component that is injected
- * into a controller. The interface represents a counter that returns a
- * incremented number each time it is called.
- *
- * The {@link Modules} class binds this interface to the
- * {@link AtomicCounter} implementation.
- */
-public interface Counter {
- int nextCount();
-}
diff --git a/play-framework/introduction/app/views/index.scala.html b/play-framework/introduction/app/views/index.scala.html
index 4539f5a10b..68d37fb1d4 100644
--- a/play-framework/introduction/app/views/index.scala.html
+++ b/play-framework/introduction/app/views/index.scala.html
@@ -1,20 +1,5 @@
-@*
- * This template takes a single argument, a String containing a
- * message to display.
- *@
-@(message: String)
+@()
-@*
- * Call the `main` template with two arguments. The first
- * argument is a `String` with the title of the page, the second
- * argument is an `Html` object containing the body of the page.
- *@
@main("Welcome to Play") {
-
- @*
- * Get an `Html` object by calling the built-in Play welcome
- * template and passing a `String` message.
- *@
- @play20.welcome(message, style = "Java")
-
+
Welcome to Play!
}
diff --git a/play-framework/introduction/app/views/main.scala.html b/play-framework/introduction/app/views/main.scala.html
index 9414f4be6e..c5f755f236 100644
--- a/play-framework/introduction/app/views/main.scala.html
+++ b/play-framework/introduction/app/views/main.scala.html
@@ -13,11 +13,12 @@
@title
-
@* And here's where we render the `Html` object containing
* the page content. *@
@content
+
+