Anton Sarov
DevOpenSpace 2015
Java and Eclipse RCP developer by day
Play Framework developer by night
@duxanton
thanks to @elmanu for the slide
(Train station vs. Restaurant)
But with some limitations (due to time pressure, like in real life)
# Homepage
GET / controllers.Application.index()
# Display a person
GET /persons/:id controllers.Persons.show(id: Long)<a href="@routes.Application.index()">Home</a>
<!-- yields: <a href="/">... -->public class ErrorHandler extends DefaultHttpErrorHandler {
// Execute default error handling
@Inject
public ErrorHandler(Configuration configuration, Environment environment, OptionalSourceMapper sourceMapper, Provider<Router> routes) {
super(configuration, environment, sourceMapper, routes);
}
// Override page not found behavior
@Override
protected Promise<Result> onNotFound(Http.RequestHeader requestHeader, String s) {
return Promise.pure(badRequest(
views.html.notFound.render(requestHeader.uri())));
}
}Place your ErrorHandler in the project's root or register it in the application.conf
play.http.errorHandler = "my.own.ErrorHandler"// bind the form to the data coming from the request
DynamicForm dynamicForm = Form.form().bindFromRequest();
// extract single fields
String username = dynamicForm.get("username");
^-- matches the name of the HTML fieldpublic static final Form<LoginData> loginForm = Form.form(LoginData.class);
Form<LoginData> submittedForm = loginForm.bindFromRequest();
if (submittedForm.hasErrors()) {
return badRequest("Username and password validation failed.");
} else {
String username = submittedForm.get().getUsername();
return ok("Hello, " + username);
}Signed cookies
session().clear();| Operation | Code |
|---|---|
| Add | |
| Get | |
| Remove | |
| Clear |
session("someKey");session().remove("someKey");session("someKey", someValue);Think "Map"
a.k.a. Action Chaining
@Security.Authenticated(Secured.class)
public Result index() {
return ok(views.html.index.render());
}import play.mvc.*;
import play.mvc.Http.*;
public class Secured extends Security.Authenticator {
@Override
public String getUsername(Context ctx) {
return ctx.session().get("username");
}
@Override
public Result onUnauthorized(Context ctx) {
return redirect(routes.Application.login());
}
}import play.libs.ws.*;
import static play.libs.F.Promise;
WSRequest request = WS.url("http://google.com");
Promise<WSResponse> promiseResponse = request.get();
//NOTICE: HTTP GET ^WSRequest request =
WS.url("http://google.com")
.setRequestTimeout(1000)
.setQueryParameter("q", "Play Framework");import play.libs.ws.*;
import static play.libs.F.Promise;
Promise<WSResponse> promiseResponse =
WS.url("http://example.com")
.setContentType("application/x-www-form-urlencoded")
.post("param1=value1");import play.libs.ws.*;
import java.util.concurrent.TimeUnit;
import static play.libs.F.Promise;
Promise<WSResponse> promiseResponse =
WS.url("http://google.com").get();
WSResponse response = promiseResponse.get(10, TimeUnit.SECONDS);
// ^^ Blocks thread until service respondspublic Result auth() {
JsonNode json = request().body().asJson();
if (json==null) {
return badRequest("Oh, I actually expected JSON data");
} else {
// happy path
}
}
// or even better
@BodyParser.Of(BodyParser.Json.class)
public Result auth() {
JsonNode json = request().body().asJson();
}public Result sayHello() {
ObjectNode result = Json.newObject();
result.put("exampleField1", "foobar");
result.put("exampleField2", "Hello world!");
return ok(result);
}project/plugins.sbt
build.sbt
lazy val myProject = (project in file(".")).enablePlugins(PlayJava, PlayEbean)addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "1.0.0")conf/application.conf
ebean.default = ["models.*"]Quiz: what happens when Evolutions are enabled and we change the model?
(with Akka)
// given an ActorSystem system
system.scheduler().scheduleOnce(
Duration.create(10, TimeUnit.MILLISECONDS),
() -> file.delete(), // Runnable object here
system.dispatcher()
);data binding
directives
backend
public class HelloActorProtocol {
public static class SayHello {
public final String name;
public SayHello(String name) {
this.name = name;
}
}
}
import akka.actor.*;
public class HelloActor extends UntypedActor {
public static Props props = Props.create(HelloActor.class);
public void onReceive(Object msg) throws Exception {
if (msg instanceof SayHello) {
sender().tell("Hello, " + ((SayHello) msg).name, self());
}
}
}import akka.actor._
object HelloActor {
def props = Props[HelloActor]
case class SayHello(name: String)
}
class HelloActor extends Actor {
import HelloActor._
def receive = {
case SayHello(name: String) =>
sender() ! "Hello, " + name
}
}