This commit is contained in:
Jonathan Cook
2019-10-23 15:01:44 +02:00
parent db85c8f275
commit 684ec0d2e3
20486 changed files with 1642483 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
## Play Framework
This module contains articles about the Play Framework.
### Relevant Articles:
- [REST API with Play Framework in Java](https://www.baeldung.com/rest-api-with-play)
- [Routing In Play Applications in Java](https://www.baeldung.com/routing-in-play)
- [Introduction To Play In Java](https://www.baeldung.com/java-intro-to-the-play-framework)
+9
View File
@@ -0,0 +1,9 @@
logs
target
/.idea
/.g8
/.idea_modules
/.classpath
/.project
/.settings
/RUNNING_PID
@@ -0,0 +1,68 @@
package controllers;
import play.libs.concurrent.HttpExecutionContext;
import play.mvc.*;
import play.twirl.api.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.
* The configuration in the <code>routes</code> file means that
* this method will be called when the application receives a
* <code>GET</code> request with a path of <code>/</code>.
*/
public Result index() {
return ok(views.html.index.render());
}
public Result applyHtml() {
return ok(Html.apply("<h1>This text will appear as a heading 1</h1>"));
}
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<Result> 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");
}
}
@@ -0,0 +1,5 @@
@()
@main("Welcome to Play") {
<h1>Welcome to Play!</h1>
}
@@ -0,0 +1,24 @@
@*
* This template is called from the `index` template. This template
* handles the rendering of the page header and body tags. It takes
* two arguments, a `String` for the title of the page and an `Html`
* object to insert into the body of the page.
*@
@(title: String)(content: Html)
<!DOCTYPE html>
<html lang="en">
<head>
@* Here's where we render the page title `String`. *@
<title>@title</title>
<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
</head>
<body>
@* And here's where we render the `Html` object containing
* the page content. *@
@content
<script src="@routes.Assets.versioned("javascripts/main.js")" type="text/javascript"></script>
</body>
</html>
+10
View File
@@ -0,0 +1,10 @@
name := """introduction"""
organization := "com.baeldung"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayJava)
scalaVersion := "2.13.0"
libraryDependencies += guice
@@ -0,0 +1,2 @@
# This is the main configuration file for the application.
# https://www.playframework.com/documentation/latest/ConfigFile
@@ -0,0 +1,35 @@
<!-- https://www.playframework.com/documentation/latest/SettingsLogger -->
<configuration>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${application.home:-.}/logs/application.log</file>
<encoder>
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="STDOUT" />
</appender>
<logger name="play" level="INFO" />
<logger name="application" level="DEBUG" />
<root level="WARN">
<appender-ref ref="ASYNCFILE" />
<appender-ref ref="ASYNCSTDOUT" />
</root>
</configuration>
+15
View File
@@ -0,0 +1,15 @@
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~
# An example controller showing a sample home page
GET / controllers.HomeController.index
GET /baeldung/html controllers.HomeController.applyHtml
GET /baeldung/bad-req controllers.HomeController.badRequestPage
GET /baeldung/not-found controllers.HomeController.notFoundPage
GET /baeldung/custom-content-type controllers.HomeController.customContentType
GET /baeldung/async controllers.HomeController.asyncOperation
GET /baeldung/headers controllers.HomeController.setHeaders
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
@@ -0,0 +1 @@
sbt.version=1.2.8
@@ -0,0 +1,7 @@
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.3")
// Defines scaffolding (found under .g8 folder)
// http://www.foundweekends.org/giter8/scaffolding.html
// sbt "g8Scaffold form"
addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0")
Binary file not shown.

After

Width:  |  Height:  |  Size: 687 B

@@ -0,0 +1,97 @@
package controllers;
import org.junit.Test;
import play.Application;
import play.inject.guice.GuiceApplicationBuilder;
import play.mvc.Http;
import play.mvc.Result;
import play.test.WithApplication;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static play.mvc.Http.Status.*;
import static play.test.Helpers.GET;
import static play.test.Helpers.route;
public class HomeControllerUnitTest extends WithApplication {
@Override
protected Application provideApplication() {
return new GuiceApplicationBuilder().build();
}
@Test
public void givenRequest_whenRootPath_ThenStatusOkay() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/");
Result result = route(app, request);
assertEquals(OK, result.status());
}
@Test
public void givenRequest_whenHtmlPath_ThenStatusOkay() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/baeldung/html");
Result result = route(app, request);
assertEquals(OK, result.status());
}
@Test
public void givenRequest_whenBadRequest_ThenStatusBadRequest() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/baeldung/bad-req");
Result result = route(app, request);
assertEquals(BAD_REQUEST, result.status());
}
@Test
public void givenRequest_whenNotFound_ThenStatusNotFound() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/baeldung/not-found");
Result result = route(app, request);
assertEquals(NOT_FOUND, result.status());
}
@Test
public void givenRequest_whenCustomContentTypePath_ThenContextTypeTextHtml() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/baeldung/custom-content-type");
Result result = route(app, request);
assertTrue(result.contentType().isPresent());
assertEquals("text/html", result.contentType().get());
}
@Test
public void givenRequest_whenAsyncPath_ThenStatusOkay() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/baeldung/async");
Result result = route(app, request);
assertEquals(OK, result.status());
}
@Test
public void givenRequest_whenHeadersPath_ThenCustomHeaderFieldSet() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/baeldung/headers");
Result result = route(app, request);
final Optional<String> headerOptional = result.header("Header-Key");
assertTrue(headerOptional.isPresent());
assertEquals("Some value", headerOptional.get());
}
}
@@ -0,0 +1,53 @@
package controllers;
import play.libs.concurrent.HttpExecutionContext;
import play.mvc.*;
import play.twirl.api.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 {
/**
* An action that renders an HTML page with a welcome message.
* The configuration in the <code>routes</code> file means that
* this method will be called when the application receives a
* <code>GET</code> request with a path of <code>/</code>.
*/
public Result index() {
return ok(views.html.index.render());
}
public Result writer(String author) {
return ok("Routing in Play by " + author);
}
public Result viewUser(String userId) {
final String response = String.format("Got user id {} in request.", userId);
return ok(response);
}
public Result greet(String name, int age) {
return ok("Hello " + name + ", you are " + age + " years old");
}
public Result squareMe(Long num) {
return ok(num + " Squared is " + (num * num));
}
public Result writer(String author, int id) {
return ok("Routing in Play by: " + author + " ID: " + id);
}
public Result introduceMe(String data) {
String[] clientData = data.split(",");
return ok("Your name is " + clientData[0] + ", you are " + clientData[1] + " years old");
}
}
@@ -0,0 +1,5 @@
@()
@main("Welcome to Play") {
<h1>Welcome to Play!</h1>
}
@@ -0,0 +1,24 @@
@*
* This template is called from the `index` template. This template
* handles the rendering of the page header and body tags. It takes
* two arguments, a `String` for the title of the page and an `Html`
* object to insert into the body of the page.
*@
@(title: String)(content: Html)
<!DOCTYPE html>
<html lang="en">
<head>
@* Here's where we render the page title `String`. *@
<title>@title</title>
<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
</head>
<body>
@* And here's where we render the `Html` object containing
* the page content. *@
@content
<script src="@routes.Assets.versioned("javascripts/main.js")" type="text/javascript"></script>
</body>
</html>
+10
View File
@@ -0,0 +1,10 @@
name := """play-routing"""
organization := "com.baeldung"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayJava)
scalaVersion := "2.13.0"
libraryDependencies += guice
@@ -0,0 +1,2 @@
# This is the main configuration file for the application.
# https://www.playframework.com/documentation/latest/ConfigFile
@@ -0,0 +1,35 @@
<!-- https://www.playframework.com/documentation/latest/SettingsLogger -->
<configuration>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${application.home:-.}/logs/application.log</file>
<encoder>
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="STDOUT" />
</appender>
<logger name="play" level="INFO" />
<logger name="application" level="DEBUG" />
<root level="WARN">
<appender-ref ref="ASYNCFILE" />
<appender-ref ref="ASYNCSTDOUT" />
</root>
</configuration>
@@ -0,0 +1,15 @@
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~
# An example controller showing a sample home page
GET / controllers.HomeController.index
GET /writer controllers.HomeController.writer(author = "Baeldung", id: Int ?= 1)
GET /writer/:author controllers.HomeController.writer(author: String, id: Int ?= 1)
GET /baeldung/:id controllers.HomeController.viewUser(id: String)
GET /greet/:name/:age controllers.HomeController.greet(name: String, age: Integer)
GET /square/$num<[0-9]+> controllers.HomeController.squareMe(num: Long)
GET /*data controllers.HomeController.introduceMe(data)
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
@@ -0,0 +1 @@
sbt.version=1.2.8
@@ -0,0 +1,7 @@
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.3")
// Defines scaffolding (found under .g8 folder)
// http://www.foundweekends.org/giter8/scaffolding.html
// sbt "g8Scaffold form"
addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0")
Binary file not shown.

After

Width:  |  Height:  |  Size: 687 B

@@ -0,0 +1,36 @@
package controllers;
import org.junit.Test;
import play.Application;
import play.inject.guice.GuiceApplicationBuilder;
import play.mvc.Http;
import play.mvc.Result;
import play.test.WithApplication;
import play.twirl.api.Html;
import java.util.Optional;
import java.util.concurrent.CompletionStage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static play.mvc.Http.Status.*;
import static play.test.Helpers.GET;
import static play.test.Helpers.route;
public class HomeControllerUnitTest extends WithApplication {
@Override
protected Application provideApplication() {
return new GuiceApplicationBuilder().build();
}
@Test
public void givenRequest_whenRootPath_ThenStatusOkay() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/");
Result result = route(app, request);
assertEquals(OK, result.status());
}
}
+9
View File
@@ -0,0 +1,9 @@
logs
target
/.idea
/.g8
/.idea_modules
/.classpath
/.project
/.settings
/RUNNING_PID
@@ -0,0 +1,91 @@
package controllers;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import model.Student;
import play.libs.Json;
import play.libs.concurrent.HttpExecutionContext;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Result;
import store.StudentStore;
import utils.Util;
import javax.inject.Inject;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletionStage;
import static java.util.concurrent.CompletableFuture.supplyAsync;
public class StudentController extends Controller {
private HttpExecutionContext ec;
private StudentStore studentStore;
@Inject
public StudentController(HttpExecutionContext ec, StudentStore studentStore) {
this.studentStore = studentStore;
this.ec = ec;
}
public CompletionStage<Result> create(Http.Request request) {
JsonNode json = request.body().asJson();
return supplyAsync(() -> {
if (json == null) {
return badRequest(Util.createResponse("Expecting Json data", false));
}
Optional<Student> studentOptional = studentStore.addStudent(Json.fromJson(json, Student.class));
return studentOptional.map(student -> {
JsonNode jsonObject = Json.toJson(student);
return created(Util.createResponse(jsonObject, true));
}).orElse(internalServerError(Util.createResponse("Could not create data.", false)));
}, ec.current());
}
public CompletionStage<Result> listStudents() {
return supplyAsync(() -> {
Set<Student> result = studentStore.getAllStudents();
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonData = mapper.convertValue(result, JsonNode.class);
return ok(Util.createResponse(jsonData, true));
}, ec.current());
}
public CompletionStage<Result> retrieve(int id) {
return supplyAsync(() -> {
final Optional<Student> studentOptional = studentStore.getStudent(id);
return studentOptional.map(student -> {
JsonNode jsonObjects = Json.toJson(student);
return ok(Util.createResponse(jsonObjects, true));
}).orElse(notFound(Util.createResponse("Student with id:" + id + " not found", false)));
}, ec.current());
}
public CompletionStage<Result> update(Http.Request request) {
JsonNode json = request.body().asJson();
return supplyAsync(() -> {
if (json == null) {
return badRequest(Util.createResponse("Expecting Json data", false));
}
Optional<Student> studentOptional = studentStore.updateStudent(Json.fromJson(json, Student.class));
return studentOptional.map(student -> {
if (student == null) {
return notFound(Util.createResponse("Student not found", false));
}
JsonNode jsonObject = Json.toJson(student);
return ok(Util.createResponse(jsonObject, true));
}).orElse(internalServerError(Util.createResponse("Could not create data.", false)));
}, ec.current());
}
public CompletionStage<Result> delete(int id) {
return supplyAsync(() -> {
boolean status = studentStore.deleteStudent(id);
if (!status) {
return notFound(Util.createResponse("Student with id:" + id + " not found", false));
}
return ok(Util.createResponse("Student with id:" + id + " deleted", true));
}, ec.current());
}
}
@@ -0,0 +1,50 @@
package model;
public class Student {
private String firstName;
private String lastName;
private int age;
private int id;
public Student() {
}
public Student(String firstName, String lastName, int age, int id) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
@@ -0,0 +1,37 @@
package store;
import model.Student;
import java.util.*;
public class StudentStore {
private Map<Integer, Student> students = new HashMap<>();
public Optional<Student> addStudent(Student student) {
int id = students.size();
student.setId(id);
students.put(id, student);
return Optional.ofNullable(student);
}
public Optional<Student> getStudent(int id) {
return Optional.ofNullable(students.get(id));
}
public Set<Student> getAllStudents() {
return new HashSet<>(students.values());
}
public Optional<Student> updateStudent(Student student) {
int id = student.getId();
if (students.containsKey(id)) {
students.put(id, student);
return Optional.ofNullable(student);
}
return Optional.empty();
}
public boolean deleteStudent(int id) {
return students.remove(id) != null;
}
}
@@ -0,0 +1,17 @@
package utils;
import com.fasterxml.jackson.databind.node.ObjectNode;
import play.libs.Json;
public class Util {
public static ObjectNode createResponse(Object response, boolean ok) {
ObjectNode result = Json.newObject();
result.put("isSuccessful", ok);
if (response instanceof String) {
result.put("body", (String) response);
} else {
result.putPOJO("body", response);
}
return result;
}
}
+10
View File
@@ -0,0 +1,10 @@
name := """student-api"""
organization := "com.baeldung"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayJava)
scalaVersion := "2.13.0"
libraryDependencies += guice
@@ -0,0 +1,2 @@
# This is the main configuration file for the application.
# https://www.playframework.com/documentation/latest/ConfigFile
@@ -0,0 +1,35 @@
<!-- https://www.playframework.com/documentation/latest/SettingsLogger -->
<configuration>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${application.home:-.}/logs/application.log</file>
<encoder>
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="STDOUT" />
</appender>
<logger name="play" level="INFO" />
<logger name="application" level="DEBUG" />
<root level="WARN">
<appender-ref ref="ASYNCFILE" />
<appender-ref ref="ASYNCSTDOUT" />
</root>
</configuration>
+12
View File
@@ -0,0 +1,12 @@
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~
GET / controllers.StudentController.listStudents()
GET /:id controllers.StudentController.retrieve(id:Int)
POST / controllers.StudentController.create(request: Request)
PUT / controllers.StudentController.update(request: Request)
DELETE /:id controllers.StudentController.delete(id:Int)
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
@@ -0,0 +1 @@
sbt.version=1.2.8
@@ -0,0 +1,7 @@
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.3")
// Defines scaffolding (found under .g8 folder)
// http://www.foundweekends.org/giter8/scaffolding.html
// sbt "g8Scaffold form"
addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0")
@@ -0,0 +1,95 @@
package controllers;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Test;
import play.Application;
import play.inject.guice.GuiceApplicationBuilder;
import play.libs.Json;
import play.mvc.Http;
import play.mvc.Result;
import play.test.WithApplication;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static play.mvc.Http.Status.OK;
import static play.test.Helpers.*;
public class StudentControllerUnitTest extends WithApplication {
@Override
protected Application provideApplication() {
return new GuiceApplicationBuilder().build();
}
@Test
public void givenStudentPostData_whenCreatingStudent_ThenShouldReturnCreatedStudent() {
final ObjectNode jsonNode = Json.newObject();
jsonNode.put("firstName", "John");
jsonNode.put("lastName", "Baeldung");
jsonNode.put("age", 25);
Http.RequestBuilder request = new Http.RequestBuilder()
.method(POST)
.bodyJson(jsonNode)
.uri("/");
Result result = route(app, request);
assertEquals(CREATED, result.status());
assertTrue(result.contentType().isPresent());
assertEquals("application/json", result.contentType().get());
}
@Test
public void givenUrlToListStudents_whenListingStudents_ThenShouldReturnStudentList() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/");
Result result = route(app, request);
assertEquals(OK, result.status());
assertTrue(result.contentType().isPresent());
assertEquals("application/json", result.contentType().get());
}
@Test
public void givenUrlToRetrieveSingleStudent_whenRetrievingStudent_ThenShouldReturn404NotFound() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(GET)
.uri("/1");
Result result = route(app, request);
assertEquals(NOT_FOUND, result.status());
assertTrue(result.contentType().isPresent());
assertEquals("application/json", result.contentType().get());
}
@Test
public void givenUrlToUpdateStudent_whenaUpdatingStudent_ThenShouldFail() {
final ObjectNode jsonNode = Json.newObject();
jsonNode.put("firstName", "John");
jsonNode.put("lastName", "Baeldung");
jsonNode.put("age", 25);
Http.RequestBuilder request = new Http.RequestBuilder()
.method(PUT)
.bodyJson(jsonNode)
.uri("/");
Result result = route(app, request);
assertEquals(INTERNAL_SERVER_ERROR, result.status());
assertTrue(result.contentType().isPresent());
assertEquals("application/json", result.contentType().get());
}
@Test
public void givenIdToDeleteStudent_whenDeletingStudent_ThenShouldFail() {
Http.RequestBuilder request = new Http.RequestBuilder()
.method(DELETE)
.uri("/1");
Result result = route(app, request);
assertEquals(NOT_FOUND, result.status());
assertTrue(result.contentType().isPresent());
assertEquals("application/json", result.contentType().get());
}
}