Beruflich Dokumente
Kultur Dokumente
202
GETTING STARTED WITH CONTENTS
Play Framework
Introduction to Play Framework
Routing Requests
Server-Side Templates
app
The app source directory for Java, Scala, and client
side source code.
GET THE PDF
The config directory containing the route mapping,
conf
application configuration, and log configuration.
The path part of the routes file can be parameterized to extract package controllers
information and pass it to the controller. For instance, to pull an id out of a
path, you would do this: import javax.inject.Inject
import play.api.mvc.BaseController
GET /user/:id controllers.Users.get(id: Long)
import play.api.mvc.ControllerComponents
The “:” matches on one / separated segment, allowing you to extract class FooController @Inject()(val controllerComponents:
ControllerComponents) extends BaseController {
multiple values like:
def get = Action {
GET /user/:id/:name controllers.Users.get(id: Long, name:
Ok(“Hello foo”)
String)
}
}
You can also extract the rest of the path using a “*” like this:
The primary difference with this Scala example is that the controller
GET /files/*file controllers.Files.get(file: String)
returns an Action which holds a function that takes a request (optionally
specified) and returns a response. Just as the Java controller, by default,
Paths can also use regex expressions to limit what they match on.
we use dependency injection to create an instance of the controller.
Query string parameters can be automatically extracted into controller It can be provided by Guice or it can use compile-time Dependency
method parameters. To handle a GET request to /foo?bar=neat, define a Injection. The controllerComponents instance injected has a number of
route like this: built-in utilities so that we can have simpler controllers, but as long as
you have an Action, it will work.
GET /foo controllers.FooController.get(bar: String)
The Controller class (in the Java API) has some convenience methods to
The query string parameters are type-safe, so if you set the type as Int, interact with the other parts of the request and response:
then there will be an error if the parameter cannot be converted to an Int.
METHOD DESCRIPTION
You can also have default and optional parameters.
Returns the HTTP context, which can be used
ctx() to retrieve and store data relevant to the
One of the reasons that Play compiles the routes file is to provide a
current request.
reverse routing API so that you never have to hard code URLs into your
application. Instead, you call a method in the reverse router, which returns
Can be used to access a state that is only
the route defined by the “routes” file. This enables you to easily refactor flash(), flash(String
available for a single request after the current
your URLs without breaking your app. key), and flash(String
one (this is useful for displaying messages
key, String value)
after a redirect).
CONTROLLERS
session(),
Controllers in Play are responsible for handling a request and returning session(String key), Can be used to access the session state which
a response. Here is a basic Java controller (which would live in app/ session(String key, is backed by a cookie.
controllers/FooController.java): String value)
package controllers;
Return the current HTTP request object,
import play.mvc.Result; which can be used for reading HTTP request
request()
import play.mvc.Controller; headers, body, and any other data related to
the request.
public class FooController extends Controller {
are also numerous other plugins that support a large variety of other
HTTP STATUS JAVA SCALA
templating systems. To use the Scala templates, create a something.scala.
200 OK OK OK html file in the app/views directory. The naming of the file is used to
name the function that will be called to render the template:
201 Created created() Created
406 Not Acceptable notAcceptable NotAcceptable Templates can take parameters, so the (optional) first line of a Scala
template is the parameters. Every Scala statement in a Scala template
415 Unsupported
unsupportedMediaType UnsupportedMediaType is prefixed with an @, so to specify that a template takes a String
Media Type
parameter, use the following:
500 Internal Server
internalServerError InternalServerError
Error
@(message: String)
Any status status(413, “Oops”) Status(413)(“Oops”)
The body of the template is just a combination of “@” prefixed Scala
Controllers in Play are internally asynchronous and non-blocking, and statements and raw HTML. For instance:
there is support for using non-blocking APIs in a more idiomatic way. For
@(title: String, message: String)
example, you can just return a Result directly, as shown before, or your
actions can return CompletableFuture<Result>:
<html>
<head>
public CompletableFuture<Result> getAsync() { <title>@title</title>
// Some async API call </head>
CompletableFuture<String> asyncApiResponse = <body>
someAsyncApi(); <h1>@message</h1>
return asyncApiResponse </body>
.thenApply(value -> ok(“Api Result: “ + value)); </html>
}
Since the Scala templates are compiled into functions, they are easily
composed. If the previous example is named main.scala.html, then to
In Scala, there is Action.async to better integrate with APIs returning
reuse it from within another template, simply do this:
a Future:
@main(“My Page Title”, “Some message”)
def getAsync = Action.async {
val asyncApiResponse: Future[String] = someAsyncApi()
asyncApiResponse.map(value => Ok(“Api Result: “ + value)) Typical template operations like loops just use normal Scala expressions,
} like so:
Interceptors can be added to controllers in order to add security, logging, @for(name <- names) {
<li>@name</li>
caching, and other custom behaviors. This is called Action Composition. }
In Play’s Java API, annotations are used to add the interceptors. In Scala,
Action Composition is achieved through functional composition. A conditional “if” statement would look like:
Controllers go much deeper than the typical request and response @if(names.isEmpty()) {
<h1>Nothing to display</h1>
handling. For instance, a controller can return a stream or it can be
} else {
used to setup a push connection (Comet, EvzentSource, WebSocket, <h1>@{names.size()} names!</h1>
etc). Controllers can also handle more than just HTML; they can be used }
for JSON, binary files, or any content type using custom Body Parsers.
The Scala templates include a number of other features and patterns,
like reusable HTML components, including forms via the @form function.
SERVER-SIDE TEMPLATES One of the huge benefits of the Scala templates is that you will see
Web applications can use server-side templates as a way to create HTML compile errors in your browser just like you do with controllers, routes,
content. In Play, the default server-side templating system is Twirl. There and everything else that is compiled by Play.
JSON These examples show serializing and de-serializing an object. Both the
Java and Scala APIs in Play have methods for traversing a JSON structure
In addition to regular HTML content, Play controllers can also receive to locate and extract data, as well as methods to create and manipulate
and return JSON serialized data. The Play Java API wraps the popular JSON structures.
Jackson library with some convenience functions. Here is an example
Java controller that has actions to get a User from somewhere (a To set up routing to either of these controller methods, add the following
database, for example) and transform it to JSON, and another action to to your routes file:
receive a JSON, parse it to a User object, and save it. Let’s first assume
GET /users/:id controllers.UsersController.get(id:
that we have the following model:
Long)
package models; POST /users controllers.UsersControllers.save
saveUserSomehow(user); To load an asset via a server-side template, use the reverse router to get
return created(“User was created”); the right URL, like so:
}
}
<img src=”@routes.Assets.at(“images/favicon.png”)” >
The same thing in Scala works in a similar way, but uses a macro-based Given the previous routing definition, the reverse router will resolve that
API to generate the serializer and de-serializer at compile time, thus to the /assets/images/favicon.png path.
avoiding the use of runtime reflection. Again, let’s first create a
model class: pa
ASSET COMPILER
package models Play has an Asset Compiler built-in that will compile client-side assets
case class User(name: String, email: String) like CoffeeScript and LESS as part of the normal compilation process.
This process will also minify JavaScript resources to reduce their size.
And the controller: Assets to be compiled go in either the app/assets/javascripts or app/
assets/stylesheets directory. For example, a new app/assets/javascripts/
package controllers
index.coffee file will be compiled and added to the classpath as assets/
import models._ javascripts/index.js and minified as assets/stylesheets/index.min.js. To
import play.api.mvc._
import play.api.libs.json.Json load the minified JavaScript via a server-side template, use
testing framework). You can test different parts of a Play application To read that config in Java, you need to inject a Config object:
independently without starting a server, or your tests can also start a
import javax.inject.Inject;
Play server, make actual requests against the server, and test the UI with
Selenium through a fake browser (HTMLUnit) or through a real browser import com.typesafe.config.Config;
(Chrome, Firefox, etc). Here is a simple Java and JUnit test of a controller:
public class FooReader {
package controllers;
private final Config config;
import org.junit.Test;
import play.Application; @Inject
import play.inject.guice.GuiceApplicationBuilder; public FooReader(Config config) {
import play.mvc.Http; this.config = config;
import play.mvc.Result; }
import play.test.WithApplication;
public String getFoo() {
import static org.junit.Assert.assertEquals; return this.config.getString(“foo”);
import static play.mvc.Http.Status.OK; }
import static play.test.Helpers.GET; }
import static play.test.Helpers.route;
public class HomeControllerTest extends WithApplication { In Scala, things are similar, except you need to inject play.api.
@Test Configuration instead:
public void testIndex() {
Http.RequestBuilder request = new Http.RequestBuilder() import javax.inject.Inject
.method(GET)
import play.api.Configuration
.uri(“/”);
} You can specify additional config files to deal with configuration that
varies between environments. Play’s config system is built on the
The same thing with Scala and ScalaTest would be Typesafe Config library. See more about how Play uses it here.
package controllers
BUILD
import org.scalatestplus.play._ Play uses the sbt build tool for managing dependencies, compiling the
import org.scalatestplus.play.guice._ app, running the app, running the tests, and packaging the app. The
import play.api.test._
import play.api.test.Helpers._
project/build.properties file specifies the version of sbt to use. Any sbt
plugins can be added in the project/plugins.sbt file. The primary build
class HomeControllerSpec extends PlaySpec with
definition is in the build.sbt file, which will look something like this:
GuiceOneAppPerTest {
Play has a number of optional dependencies with shortcut aliases: • Lightbend Project Starter contains a number of other templates
that will get you started learning about other aspects of Play
DEPENDENCY JAVA SCALA developers.lightbend.com/start/?group=play
JDBC Connection Pool and APIs jdbc javaJdbc • Creating a REST API with Play
github.com/playframework/play-scala-rest-api-example (see github.
com/playframework/play-java-rest-api-example for Java)
ehcache (or ehcache (or
Cache API
cacheApi) cacheApi)
• Play and JPA
github.com/playframework/play-java-jpa-example
Built-in Filters (gzip, etc) filters filters
• Official and third-party tutorials
playframework.com/documentation/2.6.x/Tutorials
Guice APIs and Dependencies guice guide
MARCOS PEREIRA I’m an experienced developer and product manager based in Rio de Janeiro, Brazil. Over
my career, I have worked as a developer, and also as a manager with a focus on how software can transform
business. I first started contributing to Play around December of 2014, and have been one of our most
active contributors since then. Regarding Play, I have been involved in many discussions, code reviews, and
improvements to the code and documentation. Also, I took an active role in helping out the Play community
through the Play mailing list and public forums, like StackOverflow. Since December of 2016, I’m now working
for Lightbend as one of the core developers for PlayFramework.
DZone communities deliver over 6 million pages each month to more than
3.3 million software developers, architects and decision makers. DZone offers
something for everyone, including news, tutorials, cheat sheets, research
guides, feature articles, source code and more.