diff --git a/play-framework/student-api/.gitignore b/play-framework/student-api/.gitignore new file mode 100644 index 0000000000..eb372fc719 --- /dev/null +++ b/play-framework/student-api/.gitignore @@ -0,0 +1,8 @@ +logs +target +/.idea +/.idea_modules +/.classpath +/.project +/.settings +/RUNNING_PID diff --git a/play-framework/student-api/LICENSE b/play-framework/student-api/LICENSE new file mode 100644 index 0000000000..4baedcb95f --- /dev/null +++ b/play-framework/student-api/LICENSE @@ -0,0 +1,8 @@ +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/student-api/README b/play-framework/student-api/README new file mode 100644 index 0000000000..f21d092edf --- /dev/null +++ b/play-framework/student-api/README @@ -0,0 +1,49 @@ +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/student-api/app/Filters.java b/play-framework/student-api/app/Filters.java new file mode 100644 index 0000000000..255de8ca93 --- /dev/null +++ b/play-framework/student-api/app/Filters.java @@ -0,0 +1,46 @@ +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/student-api/app/Module.java b/play-framework/student-api/app/Module.java new file mode 100644 index 0000000000..6e7d1766ef --- /dev/null +++ b/play-framework/student-api/app/Module.java @@ -0,0 +1,31 @@ +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/student-api/app/controllers/AsyncController.java b/play-framework/student-api/app/controllers/AsyncController.java new file mode 100644 index 0000000000..33cd112837 --- /dev/null +++ b/play-framework/student-api/app/controllers/AsyncController.java @@ -0,0 +1,60 @@ +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/student-api/app/controllers/CountController.java b/play-framework/student-api/app/controllers/CountController.java new file mode 100644 index 0000000000..02fcb15f8e --- /dev/null +++ b/play-framework/student-api/app/controllers/CountController.java @@ -0,0 +1,35 @@ +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/student-api/app/controllers/HomeController.java b/play-framework/student-api/app/controllers/HomeController.java new file mode 100644 index 0000000000..6a79856eb4 --- /dev/null +++ b/play-framework/student-api/app/controllers/HomeController.java @@ -0,0 +1,23 @@ +package controllers; + +import play.mvc.*; + +import views.html.*; + +/** + * 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 routes file means that + * this method will be called when the application receives a + * GET request with a path of /. + */ + public Result index() { + return ok(index.render("Your new application is ready.")); + } + +} diff --git a/play-framework/student-api/app/controllers/StudentController.java b/play-framework/student-api/app/controllers/StudentController.java new file mode 100644 index 0000000000..0adedfa432 --- /dev/null +++ b/play-framework/student-api/app/controllers/StudentController.java @@ -0,0 +1,56 @@ +package controllers; +import models.*; +import util.*; +import play.mvc.*; +import play.libs.Json; +import play.libs.Json.*; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; + +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((Student)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((Student)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) { + Student student=StudentStore.getInstance().getStudent(id); + if(student==null){ + return notFound(Util.createResponse("Student with id:"+id+" not found",false)); + } + JsonNode jsonObjects=Json.toJson(student); + return ok(Util.createResponse(jsonObjects,true)); + } + public Result listStudents() { + List 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) { + boolean status=StudentStore.getInstance().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)); + } + +} diff --git a/play-framework/student-api/app/filters/ExampleFilter.java b/play-framework/student-api/app/filters/ExampleFilter.java new file mode 100644 index 0000000000..67a6a36cc3 --- /dev/null +++ b/play-framework/student-api/app/filters/ExampleFilter.java @@ -0,0 +1,45 @@ +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/student-api/app/models/Student.java b/play-framework/student-api/app/models/Student.java new file mode 100644 index 0000000000..dc539767bd --- /dev/null +++ b/play-framework/student-api/app/models/Student.java @@ -0,0 +1,47 @@ +package models; +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) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + } + + 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; + } + +} diff --git a/play-framework/student-api/app/models/StudentStore.java b/play-framework/student-api/app/models/StudentStore.java new file mode 100644 index 0000000000..3290e141cd --- /dev/null +++ b/play-framework/student-api/app/models/StudentStore.java @@ -0,0 +1,52 @@ +package models; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +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() + 1; + student.setId(id); + students.put(id, student); + return student; + } + + public Student getStudent(int id) { + if (students.containsKey(id)) + return students.get(id); + return null; + } + + public List getAllStudents() { + return new ArrayList(students.values()); + } + + public Student updateStudent(Student student) { + int id=student.getId(); + if (students.containsKey(id)) { + student.setId(id); + students.put(id, student); + return student; + } + return null; + } + + public boolean deleteStudent(int id) { + + if (!students.containsKey(id)) + return false; + students.remove(id); + return true; + + } +} \ No newline at end of file diff --git a/play-framework/student-api/app/services/ApplicationTimer.java b/play-framework/student-api/app/services/ApplicationTimer.java new file mode 100644 index 0000000000..a951562b1d --- /dev/null +++ b/play-framework/student-api/app/services/ApplicationTimer.java @@ -0,0 +1,50 @@ +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/student-api/app/services/AtomicCounter.java b/play-framework/student-api/app/services/AtomicCounter.java new file mode 100644 index 0000000000..41f741cbf7 --- /dev/null +++ b/play-framework/student-api/app/services/AtomicCounter.java @@ -0,0 +1,26 @@ +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/student-api/app/services/Counter.java b/play-framework/student-api/app/services/Counter.java new file mode 100644 index 0000000000..dadad8b09d --- /dev/null +++ b/play-framework/student-api/app/services/Counter.java @@ -0,0 +1,13 @@ +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/student-api/app/util/Util.java b/play-framework/student-api/app/util/Util.java new file mode 100644 index 0000000000..3718b50677 --- /dev/null +++ b/play-framework/student-api/app/util/Util.java @@ -0,0 +1,17 @@ +package util; +import com.fasterxml.jackson.databind.node.ObjectNode; +import play.libs.Json; +import play.libs.Json.*; +import com.fasterxml.jackson.databind.JsonNode; + +public class Util{ + public static ObjectNode createResponse(Object response,boolean ok){ + ObjectNode result = Json.newObject(); + result.put("isSuccessfull", ok); + if(response instanceof String) + result.put("body",(String)response); + else result.put("body",(JsonNode)response); + + return result; + } +} \ No newline at end of file diff --git a/play-framework/student-api/app/views/index.scala.html b/play-framework/student-api/app/views/index.scala.html new file mode 100644 index 0000000000..4539f5a10b --- /dev/null +++ b/play-framework/student-api/app/views/index.scala.html @@ -0,0 +1,20 @@ +@* + * 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") + +} diff --git a/play-framework/student-api/app/views/main.scala.html b/play-framework/student-api/app/views/main.scala.html new file mode 100644 index 0000000000..9414f4be6e --- /dev/null +++ b/play-framework/student-api/app/views/main.scala.html @@ -0,0 +1,23 @@ +@* + * 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) + + + + + @* Here's where we render the page title `String`. *@ + @title + + + + + + @* And here's where we render the `Html` object containing + * the page content. *@ + @content + + diff --git a/play-framework/student-api/bin/activator b/play-framework/student-api/bin/activator new file mode 100644 index 0000000000..a8b11d482f --- /dev/null +++ b/play-framework/student-api/bin/activator @@ -0,0 +1,397 @@ +#!/usr/bin/env bash + +### ------------------------------- ### +### Helper methods for BASH scripts ### +### ------------------------------- ### + +realpath () { +( + TARGET_FILE="$1" + FIX_CYGPATH="$2" + + cd "$(dirname "$TARGET_FILE")" + TARGET_FILE=$(basename "$TARGET_FILE") + + COUNT=0 + while [ -L "$TARGET_FILE" -a $COUNT -lt 100 ] + do + TARGET_FILE=$(readlink "$TARGET_FILE") + cd "$(dirname "$TARGET_FILE")" + TARGET_FILE=$(basename "$TARGET_FILE") + COUNT=$(($COUNT + 1)) + done + + # make sure we grab the actual windows path, instead of cygwin's path. + if [[ "x$FIX_CYGPATH" != "x" ]]; then + echo "$(cygwinpath "$(pwd -P)/$TARGET_FILE")" + else + echo "$(pwd -P)/$TARGET_FILE" + fi +) +} + + +# Uses uname to detect if we're in the odd cygwin environment. +is_cygwin() { + local os=$(uname -s) + case "$os" in + CYGWIN*) return 0 ;; + *) return 1 ;; + esac +} + +# TODO - Use nicer bash-isms here. +CYGWIN_FLAG=$(if is_cygwin; then echo true; else echo false; fi) + + +# This can fix cygwin style /cygdrive paths so we get the +# windows style paths. +cygwinpath() { + local file="$1" + if [[ "$CYGWIN_FLAG" == "true" ]]; then + echo $(cygpath -w $file) + else + echo $file + fi +} + +# Make something URI friendly +make_url() { + url="$1" + local nospaces=${url// /%20} + if is_cygwin; then + echo "/${nospaces//\\//}" + else + echo "$nospaces" + fi +} + +declare -a residual_args +declare -a java_args +declare -a scalac_args +declare -a sbt_commands +declare java_cmd=java +declare java_version +declare -r real_script_path="$(realpath "$0")" +declare -r sbt_home="$(realpath "$(dirname "$(dirname "$real_script_path")")")" +declare -r sbt_bin_dir="$(dirname "$real_script_path")" +declare -r app_version="1.3.10" + +declare -r script_name=activator +declare -r java_opts=( "${ACTIVATOR_OPTS[@]}" "${SBT_OPTS[@]}" "${JAVA_OPTS[@]}" "${java_opts[@]}" ) +userhome="$HOME" +if is_cygwin; then + # cygwin sets home to something f-d up, set to real windows homedir + userhome="$USERPROFILE" +fi +declare -r activator_user_home_dir="${userhome}/.activator" +declare -r java_opts_config_home="${activator_user_home_dir}/activatorconfig.txt" +declare -r java_opts_config_version="${activator_user_home_dir}/${app_version}/activatorconfig.txt" + +echoerr () { + echo 1>&2 "$@" +} +vlog () { + [[ $verbose || $debug ]] && echoerr "$@" +} +dlog () { + [[ $debug ]] && echoerr "$@" +} + +jar_file () { + echo "$(cygwinpath "${sbt_home}/libexec/activator-launch-${app_version}.jar")" +} + +acquire_sbt_jar () { + sbt_jar="$(jar_file)" + + if [[ ! -f "$sbt_jar" ]]; then + echoerr "Could not find launcher jar: $sbt_jar" + exit 2 + fi +} + +execRunner () { + # print the arguments one to a line, quoting any containing spaces + [[ $verbose || $debug ]] && echo "# Executing command line:" && { + for arg; do + if printf "%s\n" "$arg" | grep -q ' '; then + printf "\"%s\"\n" "$arg" + else + printf "%s\n" "$arg" + fi + done + echo "" + } + + # THis used to be exec, but we loose the ability to re-hook stty then + # for cygwin... Maybe we should flag the feature here... + "$@" +} + +addJava () { + dlog "[addJava] arg = '$1'" + java_args=( "${java_args[@]}" "$1" ) +} +addSbt () { + dlog "[addSbt] arg = '$1'" + sbt_commands=( "${sbt_commands[@]}" "$1" ) +} +addResidual () { + dlog "[residual] arg = '$1'" + residual_args=( "${residual_args[@]}" "$1" ) +} +addDebugger () { + addJava "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$1" +} + +get_mem_opts () { + # if we detect any of these settings in ${JAVA_OPTS} we need to NOT output our settings. + # The reason is the Xms/Xmx, if they don't line up, cause errors. + if [[ "${JAVA_OPTS}" == *-Xmx* ]] || [[ "${JAVA_OPTS}" == *-Xms* ]] || [[ "${JAVA_OPTS}" == *-XX:MaxPermSize* ]] || [[ "${JAVA_OPTS}" == *-XX:MaxMetaspaceSize* ]] || [[ "${JAVA_OPTS}" == *-XX:ReservedCodeCacheSize* ]]; then + echo "" + else + # a ham-fisted attempt to move some memory settings in concert + # so they need not be messed around with individually. + local mem=${1:-1024} + local codecache=$(( $mem / 8 )) + (( $codecache > 128 )) || codecache=128 + (( $codecache < 512 )) || codecache=512 + local class_metadata_size=$(( $codecache * 2 )) + local class_metadata_opt=$([[ "$java_version" < "1.8" ]] && echo "MaxPermSize" || echo "MaxMetaspaceSize") + + echo "-Xms${mem}m -Xmx${mem}m -XX:ReservedCodeCacheSize=${codecache}m -XX:${class_metadata_opt}=${class_metadata_size}m" + fi +} + +require_arg () { + local type="$1" + local opt="$2" + local arg="$3" + if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then + echo "$opt requires <$type> argument" + exit 1 + fi +} + +is_function_defined() { + declare -f "$1" > /dev/null +} + +# If we're *not* running in a terminal, and we don't have any arguments, then we need to add the 'ui' parameter +detect_terminal_for_ui() { + [[ ! -t 0 ]] && [[ "${#residual_args}" == "0" ]] && { + addResidual "ui" + } + # SPECIAL TEST FOR MAC + [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]] && [[ "${#residual_args}" == "0" ]] && { + echo "Detected MAC OSX launched script...." + echo "Swapping to UI" + addResidual "ui" + } +} + +process_args () { + while [[ $# -gt 0 ]]; do + case "$1" in + -h|-help) usage; exit 1 ;; + -v|-verbose) verbose=1 && shift ;; + -d|-debug) debug=1 && shift ;; + + -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; + -mem) require_arg integer "$1" "$2" && sbt_mem="$2" && shift 2 ;; + -jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;; + -batch) exec &1 | awk -F '"' '/version/ {print $2}') + vlog "[process_args] java_version = '$java_version'" +} + +# Detect that we have java installed. +checkJava() { + local required_version="$1" + # Now check to see if it's a good enough version + if [[ "$java_version" == "" ]]; then + echo + echo No java installations was detected. + echo Please go to http://www.java.com/getjava/ and download + echo + exit 1 + elif [[ ! "$java_version" > "$required_version" ]]; then + echo + echo The java installation you have is not up to date + echo $script_name requires at least version $required_version+, you have + echo version $java_version + echo + echo Please go to http://www.java.com/getjava/ and download + echo a valid Java Runtime and install before running $script_name. + echo + exit 1 + fi +} + + +run() { + # no jar? download it. + [[ -f "$sbt_jar" ]] || acquire_sbt_jar "$sbt_version" || { + # still no jar? uh-oh. + echo "Download failed. Obtain the sbt-launch.jar manually and place it at $sbt_jar" + exit 1 + } + + # process the combined args, then reset "$@" to the residuals + process_args "$@" + detect_terminal_for_ui + set -- "${residual_args[@]}" + argumentCount=$# + + # TODO - java check should be configurable... + checkJava "1.6" + + #If we're in cygwin, we should use the windows config, and terminal hacks + if [[ "$CYGWIN_FLAG" == "true" ]]; then + stty -icanon min 1 -echo > /dev/null 2>&1 + addJava "-Djline.terminal=jline.UnixTerminal" + addJava "-Dsbt.cygwin=true" + fi + + # run sbt + execRunner "$java_cmd" \ + "-Dactivator.home=$(make_url "$sbt_home")" \ + ${SBT_OPTS:-$default_sbt_opts} \ + $(get_mem_opts $sbt_mem) \ + ${JAVA_OPTS} \ + ${java_args[@]} \ + -jar "$sbt_jar" \ + "${sbt_commands[@]}" \ + "${residual_args[@]}" + + exit_code=$? + + # Clean up the terminal from cygwin hacks. + if [[ "$CYGWIN_FLAG" == "true" ]]; then + stty icanon echo > /dev/null 2>&1 + fi + exit $exit_code +} + + +declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" +declare -r sbt_opts_file=".sbtopts" +declare -r etc_sbt_opts_file="${sbt_home}/conf/sbtopts" +declare -r win_sbt_opts_file="${sbt_home}/conf/sbtconfig.txt" + +usage() { + cat < path to global settings/plugins directory (default: ~/.sbt) + -sbt-boot path to shared boot directory (default: ~/.sbt/boot in 0.11 series) + -ivy path to local Ivy repository (default: ~/.ivy2) + -mem set memory options (default: $sbt_mem, which is $(get_mem_opts $sbt_mem)) + -no-share use all local caches; no sharing + -no-global uses global caches, but does not use global ~/.sbt directory. + -jvm-debug Turn on JVM debugging, open at the given port. + -batch Disable interactive mode + + # sbt version (default: from project/build.properties if present, else latest release) + -sbt-version use the specified version of sbt + -sbt-jar use the specified jar as the sbt launcher + -sbt-rc use an RC version of sbt + -sbt-snapshot use a snapshot version of sbt + + # java version (default: java from PATH, currently $(java -version 2>&1 | grep version)) + -java-home alternate JAVA_HOME + + # jvm options and output control + JAVA_OPTS environment variable, if unset uses "$java_opts" + SBT_OPTS environment variable, if unset uses "$default_sbt_opts" + ACTIVATOR_OPTS Environment variable, if unset uses "" + .sbtopts if this file exists in the current directory, it is + prepended to the runner args + /etc/sbt/sbtopts if this file exists, it is prepended to the runner args + -Dkey=val pass -Dkey=val directly to the java runtime + -J-X pass option -X directly to the java runtime + (-J is stripped) + -S-X add -X to sbt's scalacOptions (-S is stripped) + +In the case of duplicated or conflicting options, the order above +shows precedence: JAVA_OPTS lowest, command line options highest. +EOM +} + + + +process_my_args () { + while [[ $# -gt 0 ]]; do + case "$1" in + -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; + -no-share) addJava "$noshare_opts" && shift ;; + -no-global) addJava "-Dsbt.global.base=$(pwd)/project/.sbtboot" && shift ;; + -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; + -sbt-dir) require_arg path "$1" "$2" && addJava "-Dsbt.global.base=$2" && shift 2 ;; + -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; + -batch) exec ^&1') do ( + if %%~j==java set JAVAINSTALLED=1 + if %%~j==openjdk set JAVAINSTALLED=1 +) + +rem Detect the same thing about javac +if "%_JAVACCMD%"=="" ( + if not "%JAVA_HOME%"=="" ( + if exist "%JAVA_HOME%\bin\javac.exe" set "_JAVACCMD=%JAVA_HOME%\bin\javac.exe" + ) +) +if "%_JAVACCMD%"=="" set _JAVACCMD=javac +for /F %%j in ('"%_JAVACCMD%" -version 2^>^&1') do ( + if %%~j==javac set JAVACINSTALLED=1 +) + +rem BAT has no logical or, so we do it OLD SCHOOL! Oppan Redmond Style +set JAVAOK=true +if not defined JAVAINSTALLED set JAVAOK=false +if not defined JAVACINSTALLED set JAVAOK=false + +if "%JAVAOK%"=="false" ( + echo. + echo A Java JDK is not installed or can't be found. + if not "%JAVA_HOME%"=="" ( + echo JAVA_HOME = "%JAVA_HOME%" + ) + echo. + echo Please go to + echo http://www.oracle.com/technetwork/java/javase/downloads/index.html + echo and download a valid Java JDK and install before running Activator. + echo. + echo If you think this message is in error, please check + echo your environment variables to see if "java.exe" and "javac.exe" are + echo available via JAVA_HOME or PATH. + echo. + if defined DOUBLECLICKED pause + exit /B 1 +) + +rem Check what Java version is being used to determine what memory options to use +for /f "tokens=3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do ( + set JAVA_VERSION=%%g +) + +rem Strips away the " characters +set JAVA_VERSION=%JAVA_VERSION:"=% + +rem TODO Check if there are existing mem settings in JAVA_OPTS/CFG_OPTS and use those instead of the below +for /f "delims=. tokens=1-3" %%v in ("%JAVA_VERSION%") do ( + set MAJOR=%%v + set MINOR=%%w + set BUILD=%%x + + set META_SIZE=-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=256M + if "!MINOR!" LSS "8" ( + set META_SIZE=-XX:PermSize=64M -XX:MaxPermSize=256M + ) + + set MEM_OPTS=!META_SIZE! + ) + +rem We use the value of the JAVA_OPTS environment variable if defined, rather than the config. +set _JAVA_OPTS=%JAVA_OPTS% +if "%_JAVA_OPTS%"=="" set _JAVA_OPTS=%CFG_OPTS% + +set DEBUG_OPTS= + +rem Loop through the arguments, building remaining args in args variable +set args= +:argsloop +if not "%~1"=="" ( + rem Checks if the argument contains "-D" and if true, adds argument 1 with 2 and puts an equal sign between them. + rem This is done since batch considers "=" to be a delimiter so we need to circumvent this behavior with a small hack. + set arg1=%~1 + if "!arg1:~0,2!"=="-D" ( + set "args=%args% "%~1"="%~2"" + shift + shift + goto argsloop + ) + + if "%~1"=="-jvm-debug" ( + if not "%~2"=="" ( + rem This piece of magic somehow checks that an argument is a number + for /F "delims=0123456789" %%i in ("%~2") do ( + set var="%%i" + ) + if defined var ( + rem Not a number, assume no argument given and default to 9999 + set JPDA_PORT=9999 + ) else ( + rem Port was given, shift arguments + set JPDA_PORT=%~2 + shift + ) + ) else ( + set JPDA_PORT=9999 + ) + shift + + set DEBUG_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=!JPDA_PORT! + goto argsloop + ) + rem else + set "args=%args% "%~1"" + shift + goto argsloop +) + +:run + +if "!args!"=="" ( + if defined DOUBLECLICKED ( + set CMDS="ui" + ) else set CMDS=!args! +) else set CMDS=!args! + +rem We add a / in front, so we get file:///C: instead of file://C: +rem Java considers the later a UNC path. +rem We also attempt a solid effort at making it URI friendly. +rem We don't even bother with UNC paths. +set JAVA_FRIENDLY_HOME_1=/!ACTIVATOR_HOME:\=/! +set JAVA_FRIENDLY_HOME=/!JAVA_FRIENDLY_HOME_1: =%%20! + +rem Checks if the command contains spaces to know if it should be wrapped in quotes or not +set NON_SPACED_CMD=%_JAVACMD: =% +if "%_JAVACMD%"=="%NON_SPACED_CMD%" %_JAVACMD% %DEBUG_OPTS% %MEM_OPTS% %ACTIVATOR_OPTS% %SBT_OPTS% %_JAVA_OPTS% "-Dactivator.home=%JAVA_FRIENDLY_HOME%" -jar "%ACTIVATOR_HOME%\libexec\%ACTIVATOR_LAUNCH_JAR%" %CMDS% +if NOT "%_JAVACMD%"=="%NON_SPACED_CMD%" "%_JAVACMD%" %DEBUG_OPTS% %MEM_OPTS% %ACTIVATOR_OPTS% %SBT_OPTS% %_JAVA_OPTS% "-Dactivator.home=%JAVA_FRIENDLY_HOME%" -jar "%ACTIVATOR_HOME%\libexec\%ACTIVATOR_LAUNCH_JAR%" %CMDS% + +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end + +@endlocal + +exit /B %ERROR_CODE% diff --git a/play-framework/student-api/build.sbt b/play-framework/student-api/build.sbt new file mode 100644 index 0000000000..0f5ea736f6 --- /dev/null +++ b/play-framework/student-api/build.sbt @@ -0,0 +1,13 @@ +name := """student-api""" + +version := "1.0-SNAPSHOT" + +lazy val root = (project in file(".")).enablePlugins(PlayJava) + +scalaVersion := "2.11.7" + +libraryDependencies ++= Seq( + javaJdbc, + cache, + javaWs +) diff --git a/play-framework/student-api/conf/application.conf b/play-framework/student-api/conf/application.conf new file mode 100644 index 0000000000..489d3f9b3e --- /dev/null +++ b/play-framework/student-api/conf/application.conf @@ -0,0 +1,353 @@ +# This is the main configuration file for the application. +# https://www.playframework.com/documentation/latest/ConfigFile +# ~~~~~ +# Play uses HOCON as its configuration file format. HOCON has a number +# of advantages over other config formats, but there are two things that +# can be used when modifying settings. +# +# You can include other configuration files in this main application.conf file: +#include "extra-config.conf" +# +# You can declare variables and substitute for them: +#mykey = ${some.value} +# +# And if an environment variable exists when there is no other subsitution, then +# HOCON will fall back to substituting environment variable: +#mykey = ${JAVA_HOME} + +## Akka +# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration +# https://www.playframework.com/documentation/latest/JavaAkka#Configuration +# ~~~~~ +# Play uses Akka internally and exposes Akka Streams and actors in Websockets and +# other streaming HTTP responses. +akka { + # "akka.log-config-on-start" is extraordinarly useful because it log the complete + # configuration at INFO level, including defaults and overrides, so it s worth + # putting at the very top. + # + # Put the following in your conf/logback.xml file: + # + # + # + # And then uncomment this line to debug the configuration. + # + #log-config-on-start = true +} + +## Secret key +# http://www.playframework.com/documentation/latest/ApplicationSecret +# ~~~~~ +# The secret key is used to sign Play's session cookie. +# This must be changed for production, but we don't recommend you change it in this file. +play.crypto.secret = "changeme" + +## Modules +# https://www.playframework.com/documentation/latest/Modules +# ~~~~~ +# Control which modules are loaded when Play starts. Note that modules are +# the replacement for "GlobalSettings", which are deprecated in 2.5.x. +# Please see https://www.playframework.com/documentation/latest/GlobalSettings +# for more information. +# +# You can also extend Play functionality by using one of the publically available +# Play modules: https://playframework.com/documentation/latest/ModuleDirectory +play.modules { + # By default, Play will load any class called Module that is defined + # in the root package (the "app" directory), or you can define them + # explicitly below. + # If there are any built-in modules that you want to disable, you can list them here. + #enabled += my.application.Module + + # If there are any built-in modules that you want to disable, you can list them here. + #disabled += "" +} + +## IDE +# https://www.playframework.com/documentation/latest/IDE +# ~~~~~ +# Depending on your IDE, you can add a hyperlink for errors that will jump you +# directly to the code location in the IDE in dev mode. The following line makes +# use of the IntelliJ IDEA REST interface: +#play.editor="http://localhost:63342/api/file/?file=%s&line=%s" + +## Internationalisation +# https://www.playframework.com/documentation/latest/JavaI18N +# https://www.playframework.com/documentation/latest/ScalaI18N +# ~~~~~ +# Play comes with its own i18n settings, which allow the user's preferred language +# to map through to internal messages, or allow the language to be stored in a cookie. +play.i18n { + # The application languages + langs = [ "en" ] + + # Whether the language cookie should be secure or not + #langCookieSecure = true + + # Whether the HTTP only attribute of the cookie should be set to true + #langCookieHttpOnly = true +} + +## Play HTTP settings +# ~~~~~ +play.http { + ## Router + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # Define the Router object to use for this application. + # This router will be looked up first when the application is starting up, + # so make sure this is the entry point. + # Furthermore, it's assumed your route file is named properly. + # So for an application router like `my.application.Router`, + # you may need to define a router file `conf/my.application.routes`. + # Default to Routes in the root package (aka "apps" folder) (and conf/routes) + #router = my.application.Router + + ## Action Creator + # https://www.playframework.com/documentation/latest/JavaActionCreator + # ~~~~~ + #actionCreator = null + + ## ErrorHandler + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # If null, will attempt to load a class called ErrorHandler in the root package, + #errorHandler = null + + ## Filters + # https://www.playframework.com/documentation/latest/ScalaHttpFilters + # https://www.playframework.com/documentation/latest/JavaHttpFilters + # ~~~~~ + # Filters run code on every request. They can be used to perform + # common logic for all your actions, e.g. adding common headers. + # Defaults to "Filters" in the root package (aka "apps" folder) + # Alternatively you can explicitly register a class here. + #filters = my.application.Filters + + ## Session & Flash + # https://www.playframework.com/documentation/latest/JavaSessionFlash + # https://www.playframework.com/documentation/latest/ScalaSessionFlash + # ~~~~~ + session { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + + # Sets the max-age field of the cookie to 5 minutes. + # NOTE: this only sets when the browser will discard the cookie. Play will consider any + # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, + # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. + #maxAge = 300 + + # Sets the domain on the session cookie. + #domain = "example.com" + } + + flash { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + } +} + +## Netty Provider +# https://www.playframework.com/documentation/latest/SettingsNetty +# ~~~~~ +play.server.netty { + # Whether the Netty wire should be logged + #log.wire = true + + # If you run Play on Linux, you can use Netty's native socket transport + # for higher performance with less garbage. + #transport = "native" +} + +## WS (HTTP Client) +# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS +# ~~~~~ +# The HTTP client primarily used for REST APIs. The default client can be +# configured directly, but you can also create different client instances +# with customized settings. You must enable this by adding to build.sbt: +# +# libraryDependencies += ws // or javaWs if using java +# +play.ws { + # Sets HTTP requests not to follow 302 requests + #followRedirects = false + + # Sets the maximum number of open HTTP connections for the client. + #ahc.maxConnectionsTotal = 50 + + ## WS SSL + # https://www.playframework.com/documentation/latest/WsSSL + # ~~~~~ + ssl { + # Configuring HTTPS with Play WS does not require programming. You can + # set up both trustManager and keyManager for mutual authentication, and + # turn on JSSE debugging in development with a reload. + #debug.handshake = true + #trustManager = { + # stores = [ + # { type = "JKS", path = "exampletrust.jks" } + # ] + #} + } +} + +## Cache +# https://www.playframework.com/documentation/latest/JavaCache +# https://www.playframework.com/documentation/latest/ScalaCache +# ~~~~~ +# Play comes with an integrated cache API that can reduce the operational +# overhead of repeated requests. You must enable this by adding to build.sbt: +# +# libraryDependencies += cache +# +play.cache { + # If you want to bind several caches, you can bind the individually + #bindCaches = ["db-cache", "user-cache", "session-cache"] +} + +## Filters +# https://www.playframework.com/documentation/latest/Filters +# ~~~~~ +# There are a number of built-in filters that can be enabled and configured +# to give Play greater security. You must enable this by adding to build.sbt: +# +# libraryDependencies += filters +# +play.filters { + ## CORS filter configuration + # https://www.playframework.com/documentation/latest/CorsFilter + # ~~~~~ + # CORS is a protocol that allows web applications to make requests from the browser + # across different domains. + # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has + # dependencies on CORS settings. + cors { + # Filter paths by a whitelist of path prefixes + #pathPrefixes = ["/some/path", ...] + + # The allowed origins. If null, all origins are allowed. + #allowedOrigins = ["http://www.example.com"] + + # The allowed HTTP methods. If null, all methods are allowed + #allowedHttpMethods = ["GET", "POST"] + } + + ## CSRF Filter + # https://www.playframework.com/documentation/latest/ScalaCsrf#Applying-a-global-CSRF-filter + # https://www.playframework.com/documentation/latest/JavaCsrf#Applying-a-global-CSRF-filter + # ~~~~~ + # Play supports multiple methods for verifying that a request is not a CSRF request. + # The primary mechanism is a CSRF token. This token gets placed either in the query string + # or body of every form submitted, and also gets placed in the users session. + # Play then verifies that both tokens are present and match. + csrf { + # Sets the cookie to be sent only over HTTPS + #cookie.secure = true + + # Defaults to CSRFErrorHandler in the root package. + #errorHandler = MyCSRFErrorHandler + } + + ## Security headers filter configuration + # https://www.playframework.com/documentation/latest/SecurityHeaders + # ~~~~~ + # Defines security headers that prevent XSS attacks. + # If enabled, then all options are set to the below configuration by default: + headers { + # The X-Frame-Options header. If null, the header is not set. + #frameOptions = "DENY" + + # The X-XSS-Protection header. If null, the header is not set. + #xssProtection = "1; mode=block" + + # The X-Content-Type-Options header. If null, the header is not set. + #contentTypeOptions = "nosniff" + + # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. + #permittedCrossDomainPolicies = "master-only" + + # The Content-Security-Policy header. If null, the header is not set. + #contentSecurityPolicy = "default-src 'self'" + } + + ## Allowed hosts filter configuration + # https://www.playframework.com/documentation/latest/AllowedHostsFilter + # ~~~~~ + # Play provides a filter that lets you configure which hosts can access your application. + # This is useful to prevent cache poisoning attacks. + hosts { + # Allow requests to example.com, its subdomains, and localhost:9000. + #allowed = [".example.com", "localhost:9000"] + } +} + +## Evolutions +# https://www.playframework.com/documentation/latest/Evolutions +# ~~~~~ +# Evolutions allows database scripts to be automatically run on startup in dev mode +# for database migrations. You must enable this by adding to build.sbt: +# +# libraryDependencies += evolutions +# +play.evolutions { + # You can disable evolutions for a specific datasource if necessary + #db.default.enabled = false +} + +## Database Connection Pool +# https://www.playframework.com/documentation/latest/SettingsJDBC +# ~~~~~ +# Play doesn't require a JDBC database to run, but you can easily enable one. +# +# libraryDependencies += jdbc +# +play.db { + # The combination of these two settings results in "db.default" as the + # default JDBC pool: + #config = "db" + #default = "default" + + # Play uses HikariCP as the default connection pool. You can override + # settings by changing the prototype: + prototype { + # Sets a fixed JDBC connection pool size of 50 + #hikaricp.minimumIdle = 50 + #hikaricp.maximumPoolSize = 50 + } +} + +## JDBC Datasource +# https://www.playframework.com/documentation/latest/JavaDatabase +# https://www.playframework.com/documentation/latest/ScalaDatabase +# ~~~~~ +# Once JDBC datasource is set up, you can work with several different +# database options: +# +# Slick (Scala preferred option): https://www.playframework.com/documentation/latest/PlaySlick +# JPA (Java preferred option): https://playframework.com/documentation/latest/JavaJPA +# EBean: https://playframework.com/documentation/latest/JavaEbean +# Anorm: https://www.playframework.com/documentation/latest/ScalaAnorm +# +db { + # You can declare as many datasources as you want. + # By convention, the default datasource is named `default` + + # https://www.playframework.com/documentation/latest/Developing-with-the-H2-Database + #default.driver = org.h2.Driver + #default.url = "jdbc:h2:mem:play" + #default.username = sa + #default.password = "" + + # You can turn on SQL logging for any datasource + # https://www.playframework.com/documentation/latest/Highlights25#Logging-SQL-statements + #default.logSql=true +} diff --git a/play-framework/student-api/conf/logback.xml b/play-framework/student-api/conf/logback.xml new file mode 100644 index 0000000000..86ec12c0af --- /dev/null +++ b/play-framework/student-api/conf/logback.xml @@ -0,0 +1,41 @@ + + + + + + + ${application.home:-.}/logs/application.log + + %date [%level] from %logger in %thread - %message%n%xException + + + + + + %coloredLevel %logger{15} - %message%n%xException{10} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/play-framework/student-api/conf/routes b/play-framework/student-api/conf/routes new file mode 100644 index 0000000000..ab55792683 --- /dev/null +++ b/play-framework/student-api/conf/routes @@ -0,0 +1,12 @@ +# Routes +# This file defines all application routes (Higher priority routes first) +# ~~~~ + +GET / controllers.StudentController.listStudents() +POST /:id controllers.StudentController.retrieve(id:Int) +POST / controllers.StudentController.create() +PUT / controllers.StudentController.update() +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) diff --git a/play-framework/student-api/libexec/activator-launch-1.3.10.jar b/play-framework/student-api/libexec/activator-launch-1.3.10.jar new file mode 100644 index 0000000000..69050e7dec Binary files /dev/null and b/play-framework/student-api/libexec/activator-launch-1.3.10.jar differ diff --git a/play-framework/student-api/project/build.properties b/play-framework/student-api/project/build.properties new file mode 100644 index 0000000000..6d9fa6badb --- /dev/null +++ b/play-framework/student-api/project/build.properties @@ -0,0 +1,4 @@ +#Activator-generated Properties +#Wed Sep 07 12:29:40 EAT 2016 +template.uuid=c373963b-f5ad-433b-8e74-178e7ae25b1c +sbt.version=0.13.11 diff --git a/play-framework/student-api/project/plugins.sbt b/play-framework/student-api/project/plugins.sbt new file mode 100644 index 0000000000..51c5b2a35a --- /dev/null +++ b/play-framework/student-api/project/plugins.sbt @@ -0,0 +1,21 @@ +// The Play plugin +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.6") + +// Web plugins +addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.1.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.3") +addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.7") +addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0") +addSbtPlugin("org.irundaia.sbt" % "sbt-sassify" % "1.4.2") + +// Play enhancer - this automatically generates getters/setters for public fields +// and rewrites accessors of these fields to use the getters/setters. Remove this +// plugin if you prefer not to have this feature, or disable on a per project +// basis using disablePlugins(PlayEnhancer) in your build.sbt +addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0") + +// Play Ebean support, to enable, uncomment this line, and enable in your build.sbt using +// enablePlugins(PlayEbean). +// addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "1.0.0") diff --git a/play-framework/student-api/public/images/favicon.png b/play-framework/student-api/public/images/favicon.png new file mode 100644 index 0000000000..c7d92d2ae4 Binary files /dev/null and b/play-framework/student-api/public/images/favicon.png differ diff --git a/play-framework/student-api/public/javascripts/hello.js b/play-framework/student-api/public/javascripts/hello.js new file mode 100644 index 0000000000..02ee13c7ca --- /dev/null +++ b/play-framework/student-api/public/javascripts/hello.js @@ -0,0 +1,3 @@ +if (window.console) { + console.log("Welcome to your Play application's JavaScript!"); +} diff --git a/play-framework/student-api/public/stylesheets/main.css b/play-framework/student-api/public/stylesheets/main.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/play-framework/student-api/test/ApplicationTest.java b/play-framework/student-api/test/ApplicationTest.java new file mode 100644 index 0000000000..3d7c4875aa --- /dev/null +++ b/play-framework/student-api/test/ApplicationTest.java @@ -0,0 +1,45 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.*; + +import play.mvc.*; +import play.test.*; +import play.data.DynamicForm; +import play.data.validation.ValidationError; +import play.data.validation.Constraints.RequiredValidator; +import play.i18n.Lang; +import play.libs.F; +import play.libs.F.*; +import play.twirl.api.Content; + +import static play.test.Helpers.*; +import static org.junit.Assert.*; + + +/** + * + * Simple (JUnit) tests that can call all parts of a play app. + * If you are interested in mocking a whole application, see the wiki for more details. + * + */ +public class ApplicationTest { + + @Test + public void simpleCheck() { + int a = 1 + 1; + assertEquals(2, a); + } + + @Test + public void renderTemplate() { + Content html = views.html.index.render("Your new application is ready."); + assertEquals("text/html", html.contentType()); + assertTrue(html.body().contains("Your new application is ready.")); + } + + +} diff --git a/play-framework/student-api/test/IntegrationTest.java b/play-framework/student-api/test/IntegrationTest.java new file mode 100644 index 0000000000..c53c71e124 --- /dev/null +++ b/play-framework/student-api/test/IntegrationTest.java @@ -0,0 +1,25 @@ +import org.junit.*; + +import play.mvc.*; +import play.test.*; + +import static play.test.Helpers.*; +import static org.junit.Assert.*; + +import static org.fluentlenium.core.filter.FilterConstructor.*; + +public class IntegrationTest { + + /** + * add your integration test here + * in this example we just check if the welcome page is being shown + */ + @Test + public void test() { + running(testServer(3333, fakeApplication(inMemoryDatabase())), HTMLUNIT, browser -> { + browser.goTo("http://localhost:3333"); + assertTrue(browser.pageSource().contains("Your new application is ready.")); + }); + } + +}