134

Play for Java v2 Meaph

Embed Size (px)

Citation preview

Page 1: Play for Java v2 Meaph
Page 2: Play for Java v2 Meaph

MEAP Edition Manning Early Access Program

Play for Java version 2

Copyright 2012 Manning Publications

For more information on this and other Manning titles go to

www.manning.com

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 3: Play for Java v2 Meaph

brief contents PART I: INTRODUCTION AND FIRST STEPS 1. Introduction to Play 2

2. The parts of an application

3. A basic CRUD application

PART II: CORE FUNCTIONALITY 4. An enterprise app, Play-style

5. Models and persistence

6. Controllers—handling HTTP requests

7. Handling user input

8. View templates—producing output

9. Security

10. Testing your applications

11. Deployment

PART III: ADVANCE TOPICS 12. Client-side development and Play

13. SBT project management

14. Convenience libraries

15. Cloud integration

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 4: Play for Java v2 Meaph

1This chapter covers:

Play isn’t really a Java web framework. Java’s involved, but that isn’t the wholestory.

The first version of Play may have been written in the Java language, but it alsoignored the conventions of the Java platform, providing a fresh alternative toexcessive enterprise architectures. Play was not based on Java Enterprise EditionAPIs and made for Java developers. Play is for web developers.

Play was not just written web developers, it was written web developers,for bywho brought high-productivity web development from modern frameworks likeRuby on Rails and Django to the the JVM. Play is for productive web developers.

Play 2 is written in Scala, but that does not mean you have to write your webapplications in Scala, or even know anything about Scala. This is because Play 2comes with a complete Java API, giving you the option to pick the language thatsuits you best. If you've used Play 1.x before, you'll notice the API has becomemore type-safe.

Play isn’t just about about Scala and type safety either. An important aspect ofPlay is the usability and attention to detail that results in a better Developer

Introduction to Play 2

What the Play framework is

What high-productivity web frameworks are about

Why Play supports both Java and Scala

What a minimal Play application looks like

1

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 5: Play for Java v2 Meaph

Experience (DX). When you add this to higher developer productivity and moreelegant APIs and architectures you get a new emergent property: Play is fun.

Play is fun. Play makes you more productive. Play is also a web framework whoseHTTP interface is simple, convenient, flexible and powerful. Most importantly,Play improves on the most popular non-Java web development languages andframeworks — PHP and Ruby on Rails — by introducing the advantages of theJava Virtual Machine (JVM).

A variety of features and qualities make Play productive and fun to use.

Declarative application URL scheme configuration.Type-safe mapping from HTTP to an idomatic Scala API.Type safe template syntax.Architecture that embraces HTML5 client technologies.Live code changes when you reload the page in your web browser.Full-stack web framework features, including persistence, security andinternationalisation.

We’ll get back to why Play makes you more productive, but first let’s look alittle more closely at what it means for Play to be a full-stack framework. Afull-stack framework gives you everything you need to build a typical webapplication, as illustrated in figure 1.1.

Figure 1.1 Play framework stack

1.1 What Play is

1.1.1 Key features

2

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 6: Play for Java v2 Meaph

Being ‘full-stack’ is not just a question of functionality, which may alreadyexist as a collection of open-source libraries. After all, what’s the point of aframework if these libraries already exist and already provide everything you needto build an application? The difference is that a full-stack framework also providesa documented pattern for using separate libraries together in a certain way, andtherefore confidence that a developer can make the separate components worktogether. Without this, you never know whether you are going to end up with twoincompatible libraries, or a badly-designed architecture.

When it comes to actually building a web application, what this all means isthat the common tasks are directly supported in a simple way, which saves youtime.

Play supports Java, and is in fact the best way to build a Java web application.Java’s success as a programming language, especially in enterprise softwaredevelopment, means that Play 1.x has been able to quickly build a large usercommunity. Especially if you are planning to use Play with Java, you get to benefitfrom this community’s size.

However, the recent years have seen the introduction of numerous JVMlanguages that provide a modern alternative to Java, usually aiming to be moretype safe, result in more concise code and support functional programming idioms,with the ultimate goal of allowing developers to be more expressive and productivewhen writing code. Scala is currently the most evolved of the new statically-typedJVM languages, and is the second language that Play supports. Scala is meant (andproven) to be a language, hence the name. Play 2 takes full advantage ofscalablethe scalability that Scala offers, which means your Java applications will get thesebenefits, too.

SIDEBAR Our sister book: Play 2 for ScalaIf you’re also interested in using Play to build web applications in Scala,then you should look at , which was written at the samePlay 2 for Scalatime as this book. The differences between Scala and Java go beyondthe syntax, and the Scala book is not just a copy of this book but withcode samples in Scala. is focused on the idiomatic usePlay 2 for Scalaof the Scala language with Play 2.

1.1.2 Java and Scala

3

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 7: Play for Java v2 Meaph

Before Play, Java web frameworks were based on the Java Servlet API, the part ofthe Java Enterprise Edition (Java EE) stack that provides the HTTP interface. JavaEE and its architectural patterns seemed like a really good idea, and brought somemuch needed structure to enterprise software development. However, this turnedout to be a really bad idea, because structure came at the cost of additionalcomplexity and low developer satistfaction. Play is different, for several reasons.

Java’s design and evolution is focused on the Java platform, which also seemedlike a good idea to developers who were trying to consolidate various kinds ofsoftware development. From a Java perspective, the web is just another externalsystem. The Servlet API, for example, is an abstraction layer over the web’s ownarchitecture that provides a more Java-like API. Unfortunately, this turns out be abad idea, because the web is more important than Java. When a web frameworkstarts an architecture fight with the web, the framework loses. What we needinstead is a web framework whose architecture embraces the web’s, and whoseAPI embraces HTTP.

The consequence of the Servlet API’s problems is complexity, mostly in the formof too many layers. This is the complexity caused by the API’s own abstractionlayers, compounded by the additional layer of a web framework that provides anAPI that is rich enough to build a web application with. You can see the differencein figure 1.2

Figure 1.2 Java EE ‘lasagne’ architecture compared to Play’s simplified architecture

The Servlet API was originally intended to be an end-user API for web

1.1.3 Play is not Java EE

LASAGNE ARCHITECTURE

4

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 8: Play for Java v2 Meaph

developers, using Servlets (the name for controller Java classes), and JavaServerPages (JSP) view templates. When new technologies eventually superceded JSP,they were layered on top, instead of eventually being folded back into Java EE,either as updates to the Servlet API or as a new API. With this approach, theServlet API becomes an additional layer that makes it harder to debug HTTPrequests. This may keep the architects happy, but at the cost of developerproductivity.

This lack of focus on productive web development is apparent within the currentstate of Java EE web development, which is now based on JavaServer Faces (JSF).JSF focuses on components and server-side state, which also seemed like a goodidea, and gave developers powerful tools for building web applications. However,again, it turned out that the resulting complexity and the mismatch with HTTPitself made JSF hard to use productively.

Java EE frameworks such as JBoss Seam did an excellent job at addressingearly deficiencies in JSF, but only by adding yet another layer to the applicationarchitecture. Since then, Java EE 6 has improved the situation by addressing JSF’sworst shortcomings, but this is certainly too little, too late.

Somewhere in the history of building web applications on the JVM, addinglayers somehow became part of the solution without being seen as a problem.Fortunately for JVM web developers, Play provides a redesigned web stack thatdoesn’t use the Servlet API and works better with HTTP and the web.

Web frameworks for web developers are different. They embrace HTTP andprovide APIs that use HTTP’s features instead of trying to hide HTTP, in the sameway that web developers build expertise in the standard web technologies —HTTP, HTML, CSS and JavaScript — instead of avoiding them.

Working with HTTP means letting the application developer make the webapplication aware of the different HTTP methods, such as GET, POST, PUT andDELETE instead of having an an RPC-style layer on top of HTTP requests, inorder to tell the application whether you want to create, update or delete data. Italso means accepting that application URLs are part of the application’s publicinterface, and should therefore be up to the application developer to design insteadof fixed by the framework.

THE JSF NON-SOLUTION

1.2 High-productivity web development

1.2.1 Working with HTTP

5

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 9: Play for Java v2 Meaph

This approach is for developers who not only work with the architecture of the

World Wide Web, instead of against it, but may have even read it .1

Footnote 1 m , W3C, 2004Architecture of the World Wide Web, Volume One(http://www.w3.org/TR/webarch/)

In the past, none of these web frameworks were written in Java, because theJava platform’s web technologies failed to emphasise simplicity, productivity andusability. This is the world that started with Perl (not Lisp as some might assume),was largely taken over by PHP, and in more recent years has seen the rise of Rubyon Rails.

In a web framework, simplicity comes from making it easy to do simple things in afew lines of code, without extensive configuration. A ‘Hello World’ in PHP is asingle line of code; the other extreme is JavaServer Faces, which requiresnumerous files of various kinds before you can even serve a blank page.

Productivity starts with being able to make a code change, reload the web pagein the browser, and see the result. This has always been the norm for many webdevelopers, while Java web frameworks and application servers often have longbuild-redeploy cycles. Java hot-deployment solutions exist, but are not standardand come at the cost of additional configuration. Although there is more toproductivity, this is what matters most.

Usability is related to developer-productivity, but also to developer-happiness.You are certainly more productive if it is easier to simply get things done, nomatter how smart you are, but a usable framework can be more than that — a joyto use. Fun, even.

As you would expect, it is very easy to do something as simple as output ‘Helloworld!’. All you need to do is use the Play command that creates a new applicationand write a couple of lines of Java code. To begin to understand Play, you shouldactually run the command and type the code, because only then will you get yourfirst experience of Play’s simplicity, productivity and usability. But to do that,you'll need to have Play installed. We'll get to that in a minute.

But first, it is interesting to talk about why there even an installation step withisPlay 2. Most web frameworks in the Java world are just libraries that you add toyou project, and bootstrap with some configuration file (such as ) orweb.xml

boilerplate code, to run in a Servlet container or application server. With these

1.2.2 Simplicity, productivity and usability

1.3 Hello Play!

6

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 10: Play for Java v2 Meaph

frameworks, there no install step. Play is more than just a library – it provides aiscomplete tool suite, including a web server and build tool.

Installing Play is easy, here's how.

First, download the latest Play 2 version from the web site at . Extract the .zip file to the location where you want tohttp://playframework.org

install Play 2 (your home directory is fine). Next, you need to add this directory toyour PATH system variable, which will make it possible for you to launch Playfrom anywhere.

Setting the PATH variable is OS-specific. Here’s the instructions for OS X,Linux and Windows:

: Open the file in a text editor, and add the path whereMac OSX /etc/paths

you installed Play to it.: Open you shell’s startup file in a text editor. The name of the fileLinux

depends on which shell you use, e.g. .bashrc for bash, .zshrc for zsh. Add thefollowing line to it: , of course with thePATH="$PATH":/path/to/play

proper path substituted.: Go to Control Panel > System and Security > System and click Windows 7

on the right-hand side. Click the button Advanced System Settings Environment. You’ll see a window listing variables (as in figure 1.3, and there shouldVariables

be a user variable called . Simply add the path to your Play installation to thePATH

end of its value.

1.3.1 Installing Play

7

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 11: Play for Java v2 Meaph

Figure 1.3 The Windows Environment Variables dialog.

SIDEBAR Mac users can use HomebrewIf you’re using Mac OS X, you could also use Homebrew to install Play2. Just use the command to install, andbrew install play

Homebrew will download and extract the latest version, and take careof adding it to your path, too.

Now, Play should be available from any new shell you open. Go ahead and tryit out: open a shell, and enter the command. You should get output similar toplay

this:

~ play _ _ _ __ | | __ _ _ _| || '_ \| |/ _' | || |_|| __/|_|\____|\__ (_)|_| |__/

play! 2.0-RC2, http://www.playframework.org

This is not a play application!

Use `play new` to create a new Play application in thecurrent directory, or go to an existing application

8

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 12: Play for Java v2 Meaph

and launch the development console using `play`.

You can also browse the complete documentation athttp://www.playframework.org.

As you can see, this command didn’t do very much yet. But Play try to bedoeshelpful: it tells you why it couldn’t to anything ("This is not a play application!"),and it suggests a command you can use to get started ( ). This will be aplay new

recurring theme when using Play: whenever something goes wrong, Play willguess what you’re trying to do, explain exactly where things went wrong, andsuggest a next step to fix it. This doesn’t limit itself to the command-line outputthough, we’ll see useful error messages like this in our browsers, too, later.

For now, let’s follow Play’s suggestion: create a new application.

A "play application" is a directory on the filesystem that contains a certainstructure that Play uses to find configuration, code and any other resources itneeds. We don’t need to create this structure ourselves – Play will do it for us whenwe use the command. This command will turn the current directoryplay new

into a Play application, or you can add the desired name of your new application asa parameter, and it’ll create that directory for your.

According to tradition, any first example in any sort of technical tutorial shouldbe called "Hello World". So go ahead and type the following command: play

. Play will ask you to confirm the name, so just hit enternew "Hello World"

when the question comes up.

~ play new "Hello World" _ _ _ __ | | __ _ _ _| || '_ \| |/ _' | || |_|| __/|_|\____|\__ (_)|_| |__/

play! 2.0-RC2, http://www.playframework.org

The new application will be created in /Users/sietse/Hello World

What is the application name?> Hello World

Which template do you want to use for this new application?

1 - Create a simple Scala application 2 - Create a simple Java application 3 - Create an empty project

1.3.2 Creating your first application

9

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 13: Play for Java v2 Meaph

>

Play is now asking us what kind of project we want. Pick option 2, Java.

> 2

OK, application Hello World is created.

Have fun!

Congratulations, you’ve just created your first Play 2 application. Let’s seewhat's inside.

The command always creates a default application with a basicplay new

structure, including a minimal HTTP routing configuration file, a controller classfor handling HTTP requests, a view template, jQuery and a default CSS style sheet.Don't worry if you don't know what all these terms mean yet, we'll cover them indetail in chapter XREF _chapter_3_getting_started.

The full contents of a newly created application is shown in figure 1.1.

Listing 1.1 Files in a new Play application

README app   controllers      Application.java   views   index.scala.html   main.scala.html conf   application.conf   routes project   Build.scala   build.properties   plugins.sbt public images    favicon.png javascripts    jquery-1.7.1.min.js stylesheets main.css target

This directory structure is common to all Play applications.Now that we've seen the files that make up our application, let's see what it

1.3.3 Play application structure

10

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 14: Play for Java v2 Meaph

looks like. Time to run the application.

Play 2 always needs to be started from within an application directory, so cd intoit: . Now, start Play simply by typing :cd "Hello World" play

~ cd Hello\ World~/Hello World play2[info] Loading project definition from /Users/sietse/Hello World/project[info] Set current project to Hello World (in build file:/Users/sietse/Hello%20World/) _ _ _ __ | | __ _ _ _| || '_ \| |/ _' | || |_|| __/|_|\____|\__ (_)|_| |__/

play! 2.0-RC2, http://www.playframework.org

> Type "help play" or "license" for more information.> Type "exit" or use Ctrl+D to leave this console.

[Hello World] $

You’re now in Play 2’s . In the console, you can run several commandsconsoleto interact with your application. We’ll be introducing some of them in thischapter, and others throughout the rest of the book, but you can always type help

to get a list of commands.play

For now, we’ll just stick to running the application. Type .run

[Hello World] $ run

[info] Updating {file:/Users/sietse/Hello%20World/}Hello World...[info] Done updating.--- (Running the application from SBT, auto-reloading is enabled) ---

[info] play - Listening for HTTP on port 9000...

(Server started, use Ctrl+D to stop and go back to the console...)

Play has just checked your application and its dependencies for updates, andstarted a web server that serves your application. Let's see what it is serving.

Now that the application is running, you can access a default welcome page at . You should see the page shown in figure 1.4http://localhost:9000/

1.3.4 Running the application

1.3.5 Accessing the running application

11

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 15: Play for Java v2 Meaph

Figure 1.4 The default welcome page for a new Play application

This is already a kind of ‘hello world’ — an example of a running applicationthat outputs something, so you can see how things fit together. This is more thanjust a static HTML file that tells you that ‘the web server is running’. Instead, thisis the minimal amount of code that can show you the web framework in action.This makes it easier to create a ‘hello world’ example than it would be if we had tostart with a completely blank slate - an empty directory that forces you to turn tothe documentation each time you create a new application, which is probably notsomething you will do every day.

Now, leaving our example application at this stage would be cheating, so weneed to change the application to produce the proper output. Besides, it doesn’tactually say ‘hello world’ yet. Let's change the welcome message.

The file in your application that controls what result is sent in response to therequest for http://localhost/ is app/controllers/Application.java. It's a regular Javaclass, which currently contains one method; . It looks like this:index

public static Result index() { return ok(index.render("Your new application is ready."));}

The method is called an method. It contains the logic thatindex action

determines the response to the current HTTP request. We'll get into more detailabout what this specific code means, later, but for now it's enough to understandthis is how Play renders the default welcome page.

Let's change the output to something else. Simply edit the file and replace the app/controllers/Application.java Application

class' method with the following.index

1.3.6 Changing the controller class

12

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 16: Play for Java v2 Meaph

public static Result index() { return ok("Hello world!");}

This defines an action method that generates an HTTP "OK" response with textcontent. Now serves a plain text documenthttp://localhost:9000/

containing the customary greeting.

The output is actually more interesting if you make a mistake. In the actionmethod, remove the closing quote from , save the file and"Hello world"

reload the page in your web browser. You get a friendly compilation error.

Figure 1.5 Compilation errors are shown in the web browser, with the relevant sourcecode highlighted.

Fix the error in the code, save the file and reload the page again. It’s fixed! Playdynamically reloads changes, so you don’t have to manually build the applicationevery time you make a change.

This is still not a proper web application example, though, because we did not useHTTP or HTML yet. Let's make it a little more interactive, and make it a properHTML page. To start with, add a new action method with a String parameter to thecontroller class:

1.3.7 Add a compilation error

1.3.8 Use an HTTP request parameter

13

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 17: Play for Java v2 Meaph

public static Result hello(String name) { return ok(index.render("Hello " + name));}

Now, if you want to try to run this new method, we need to set up a HTTP path(say, ) that corresponds to this method. We'll also want to link a HTTP/hello

query parameter called to our method's parameter. This is called name name

the parameter. To get this to work, we need to tell Play what we want tobindingdo.

The key to setting up this binding is in the file conf/routes. In fact, this file isthe reason the method we saw before works in the first place. If you openindex

up the file, you'll see the following line:

GET / controllers.Application.index()

That line is called a , and it maps a HTTP path to an action method in ourrouteapplication. In this case, it maps the root URL ('/') to . ToApplication.index

get it to accept a parameter, change it to the following:name

Next, add a new line to the file to map a different URL to ourconf/routes

new method, with an HTTP request parameter called :name

GET /hello controllers.Application.hello(name:String)

Now open and youhttp://localhost:9000/hello?name=Play!

can see how the URL’s query string parameter is passed to the controller action.

Finally, to complete this first example, we need an HTML template, because weusually use web application frameworks to generate web pages instead of plain textdocuments. Create the file with theapp/views/hello.scala.html

following content.

@(name:String)<!doctype html><html> <head> <meta charset="UTF-8"> <title>Hello</title> </head> <body> <h1>Hello <em>@name</em></h1> </body></html>

1.3.9 Add an HTML page template

14

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 18: Play for Java v2 Meaph

This is a ‘Scala template’, a template with syntax based on the Scala language.Don't worry, you don't have to learn Scala! Think of it as any other new templatelanguage.

The first line defines the parameter list — just a parameter in this case,name

and the HTML document includes an HTML tag whose content is a expressionem

— the value of the parameter. To use this template, we just have to replacename

the action method to return a result that wraps a call to the template insteadhello

of a literal:String

public static Result index(String name) { return ok(views.html.hello.render(name));}

R e l o a d t h e w e b p a g e — — and you will see thehttp://localhost:9000/hello?name=Play!

formatted HTML output.

Web developers are used to doing everything in the browser. With Play, you canalso use the console to interact with your web application’s developmentenvironment and build system. This is important for both quick experiments andautomating things.

To start the console, run the command in the application directoryplay

without an additional command:

play

If you are already running a Play application, you can just type toControl+D

stop the application and return to the console.The Play console gives you a variety of commands, including the run

command that you saw earlier. For example, you can compile the application todiscover the same compilation errors that are normally shown in the browser, suchas the missing closing quotation mark that you saw earlier:

[hello] $ compile[info] Compiling 1 Java source to hello/target/scala-2.9.1/classes...[error] hello/app/controllers/Application.java:11: unclosed string literal[error] return ok(index.render("Hello world));[error] ^[error] hello/app/controllers/Application.java:11: ')' expected

1.4 The console

15

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 19: Play for Java v2 Meaph

[error] return ok(index.render("Hello world));[error] ^[error] hello/app/controllers/Application.java:12: ';' expected[error] }[error] ^[error] hello/app/controllers/Application.java:14: reached end of file while parsing[error] }[error] ^[error] 4 errors[error] {file:hello/}hello/compile:compile: javac returned nonzero exit code[error] Total time: 0 s, completed Mar 19, 2012 11:29:53 AM[hello] $

You can also start a Scala console, which gives you direct access to yourcompiled Play application:

[hello] $ console[info] Starting scala interpreter...[info]Welcome to Scala version 2.9.1.finalCO (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).Type in expressions to have them evaluated.Type :help for more information.

scala>

As the name suggests, the Scala console uses Scala. This is because the buildtool (sbt) and the core framework are Scala-based. Like we said before, you don'thave to learn Scala to be able to use Play, but we did want to show you this usefulfeature of Play's console. Certain things are easy enough to do, and are not verydifferent from how you would do things in Java. One example of this is rendering atemplate, which is just a Scala function that you can call like this:

scala> views.html.hello.render("Play!")res1: play.api.templates.Html =

<!doctype html><html> <head> <meta charset="UTF-8"> <title>Hello</title> </head> <body> <h1>Hello <em>Play!</em></h1> </body></html>

16

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 20: Play for Java v2 Meaph

We just rendered a dynamic template in a web application that is not actuallyrunning. This has major implications for being able to test your web applicationwithout running a server.

Play was built ‘by web developers, for web developers’ — taking good ideas fromexisting high-productivity frameworks, and adding the JVM’s power and richecosystem. The result is a web framework that offers productivity and usability aswell as structure and flexibility. After starting with a first version implemented inJava, Play has now been reimplemented in Scala, which helped introduce moretype-safety throughout the framework. Many of the benefits from Scala, like it'sscalability and type safety are reflected in the Java API.

As soon as you start writing code, you go beyond Play’s background and itsfeature list to what really matters: the user-experience that determines how muchyou will enjoy using Play. The good news is that Play achieves a level ofsimplicity, productivity and usability that means that you can look forward toenjoying Play and, we hope, the rest of this book.

1.5 Summary

17

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 21: Play for Java v2 Meaph

2This chapter covers:

Now that you know what Play is all about, it’s time to start building a seriousapplication. In this chapter we’ll dive deeper into what makes up a Playapplication, and give you an introduction to all the important concepts whenbuilding a Play application. The following chapters will then explore each conceptin more detail.

In this chapter, we’ll also introduce the example application that we’ll evoleinto a full-scale enterprise-ready application as we progress through the chapters ofthis book. The application we chose to be an example of a real-world application –not the next Twitter or Facebook, which have very specific and uncommon

requirements and challenges , but something your customer might ask you to1

build. We start by creating a new application, and identifying all the files that makeup the new application. After that, we’ll set up an IDE, so that we’re ready to startthe actual coding in the next chapter.

Footnote 1 although you could very well use Play for them!m

Let’s see what we’re going to build.

The parts of an application

The introcution of our sample application

Discussing the contents of a new application

Setting up an IDE

Configuring a debugger

18

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 22: Play for Java v2 Meaph

Throughout the rest of this book, we’ll build an enterprise web application from theground up. The Acme Paperclip Company has asked us to build them a web-basedwarehouse management application. They have all sorts of plans for automation oftheir warehouse processes, but they first want us to show them that we’re up to thejob by building a simple product catalog for their product range.

The application we will build for them in this chapter is a simple CRUD2

application for maintaining a product catalog. Users will be able to browse a list ofproducts, as well as add new ones. Since this is only a proof of concept, we willsimulate storing these products – the data storage will be mocked, rather than usingan actual database. We’ll add persistence in chapter 5.

Footnote 2 Create, Retrieve, Update, Deletem

But first, let’s create a new Play application that will become our warehouseapplication. Just like we did in chapter 1, when we created the “Hello World”example, we’ll use the command. Go ahead and run play new play new

, and you’ll have a new directory that will contain awarehouse warehouse

default Play application. Let’s see what’s inside.

If you take a look at your application’s directory, you’ll see it contains thefollowing files and directories :

README app   controllers      Application.java   views   index.scala.html   main.scala.html conf   application.conf   routes project   Build.scala   build.properties   plugins.sbt public images    favicon.png javascripts    jquery-1.7.1.min.js stylesheets main.css target

2.1 Introducing our application

2.2 A rundown of a Play application

19

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 23: Play for Java v2 Meaph

We’ll have a closer look at each of the top level directories. The directoryapp

is the most important one, but we’ll skip that for now, and talk about the othersfirst.

First we’ll discuss a directory that doesn't show up in a newly createdapplication, but will be there after you run it once; the directory. There’starget

only one thing you have to know about the target directory: you should ignore it.The directory is the build process’ working directory. This is where yourtarget

compiled classes are stored, among other things. Just be sure to never commit it inyour versioning system. Actually, if you’re using git as your versioning system,you probably won’t: Play also generated a .gitignore file for you, making sure younever commit files that are generated at runtime.

Now that we know what to ignore, let’s start discussing the first directory ofinterest, the directory.conf

The directory is where you the application. Its contents look likeconf configure

this:

. application.conf routes

As you can see, this directory contains two files: and application.conf

. The file contains configuration about your Playroutes application.conf

application. This is where you’ll configure things like logging, databaseconnections, which port the server runs on, and more.

The application configuration file is loaded at startup time, and is globallyreadable. This means any code that needs to can access it. If you need someconfiguration options for your application, you can add some custom options to thefile, and use them in your own code. Play generated an example configurationwhen you ran , so open it up and poke around if you’re curious. We’llplay new

cover some of the options in here when we run into them, further in this chapterand the rest of the book.

The other file in the directory is the file. Here you can defineconf routes

your application’s – mappings from HTTP URLs to application code. Itroutesalready contains two example routes:

2.3 Play’s configuration files

20

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 24: Play for Java v2 Meaph

# Home pageGET / controllers.Application.index()

# Map static resources from the /public folder to the /assets URL pathGET /assets/*file controllers.Assets.at(path="/public", file)

Every line it the file defines a single route. Let’s focus on the firstroutes

route, we’ll explain what the second route does in section X.Any route consist of 3 parts: the HTTP , the and the ,method path action method

as illustrated in figure 2.1.

Figure 2.1 Components of a route

So, our example route maps any HTTP request for ‘/’ to GET

. This means that any GET requestcontrollers.Application.index()

for the / (root) URL is actually by the method on the handled index

class in the package. We call methods thatApplication controllers

handle requests .action methods

21

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 25: Play for Java v2 Meaph

SIDEBAR About HTTP methodsIf you’re unfamiliar with the HTTP protocol, the concept of a HTTP‘method’ may be new to you. There’s a lot of documentation to be foundabout the HTTP protocol and its methods, and what they imply. Searchthe web if your curious, but here’s a summary that will get you throughthe chapter.The method of a HTTP request signifies the purpose of your request:whether you want to retrieve a resource from the server, or postinformation to it, for example. There are a number of different methodsdefined in the HTTP specification, and some extensions to the protocoladd even more, but the two most-used methods in the HTTP standardare and .GET POSTGET is a retrieval request for a resource and contains no body,although the URL used may contain parameters (everything that comesafter the ). It is important that a GET request may have any? neverlasting effects on the server; every time you GET a URL should havethe same effect. The fancy word for this is . The mostidempotenceimportant thing to remember is that you should only use it forinformation , not for submission of data.retrievalThe POST method, on the other hand, is a request for data ,submissionand may contain a body. It is still directed at a URL, but a POSTrequest has effects server-side. A POST request is often used for formsthat create or modify information. This is why your browser will likelywarn you when you reload a URL that you just POSTed to before.There are more methods in the HTTP standard, such as PUT andDELETE, but we’ll talk about those when we’re discussing HTTP APIs.

The routes file is very important to any Play application. It allows you to‘design’ your URLs. This is a big deal. Some (if not most) other Java webframeworks actually dictate what your URLs should be, or the framework can’t doits job. Because Play gives you full control over your URL schema, you can designclean, human readable, bookmarkable URLs.

The next directory in our list is the directory.project

The project directory looks like this:

README app conf project   Build.scala

2.4 Build configuration files

22

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 26: Play for Java v2 Meaph

   build.properties   plugins.sbt public

Of these files, you’ll only deal with . Both Build.scala

and are SBT configuration files, which isbuild.properties plugins.sbt

configured just fine as it is. SBT is the build tool that Play’s console and buildprocess is based upon. We’ll tell you more about SBT in chapter XX, but don’tworry about it for now.

The file is a file you have to edit occasionally though. TheBuild.scala will

file looks like this when newly generated:

import sbt._import Keys._import PlayProject._

object ApplicationBuild extends Build {

val appName = "Hello World" val appVersion = "1.0-SNAPSHOT"

val appDependencies = Seq( // Add your project dependencies here, )

val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings( // Add your own project settings here )

}

In this file you define your application’s version number, as well as any it might need. Managed dependencies are libraries andmanaged dependencies

modules you use in your application that Play can look up and download3

automatically. This is called dependencies. You might be familiar withresolvingthis process if you’ve used Maven or Ivy before.

Footnote 3 m actually, it delegates this to SBT.

As an example, suppose you want to use Google’s Guava library to get some4

useful extra functionality on top of what the JDK standard library provides. You’dadd a dependency on version 12.0 like this:

Footnote 4 m http://code.google.com/p/guava-libraries/

object ApplicationBuild extends Build { ...

23

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 27: Play for Java v2 Meaph

val appDependencies = Seq( "com.google.guava" % "guava" % "12.0" )

...

}

The next time the application is started, Play will resolve the dependency andautomatically download the correct jar, and add it to the classpath.

The way dependency resolving works is that several pre-configured dependency are queried for the correct versions of the files you need. There arerepositories

various dependency repositories on the internet that serve the majority of thelibraries available in the Java ecosystem. The most well-known repository is theMaven central repository at maven.org.

The dependency management system is smart enough to also download yourdependencies’ dependencies, also called . If you’re usingtransitive dependenciestransitive dependencies, and you want to include a library that has lots ofdependencies itself, you no longer have to keep track of what version of what jar toput where. The dependency management system does all of this for you.

Another great benefit of using managed dependencies is that you don’t need tokeep any library files with your source files, keeping your codebase nice and small,while ensuring that it will always build (as long as any repository server containingthe files is still available). Another bonus you get is that it’s easy to upgrade alibrary to a different version: simply change the version in your dependencydeclaration, and you’re done.

Play 2 will automatically resolve any dependencies as soon as it finds anychange in this file when your application starts, so you don’t need to worry abouthaving to trigger a dependency update.

If you want to use a library that’s not in any repository (yet), for example whenit’s a new library, or one you developed in-house, you don’t to usehavedependency management to use that library. You can simply create a new directorycalled in you application’s root directory, and any jar Play finds there willlib

automatically be added to the classpath for your application.We’ll talk more about dependencies and dependency management in chapter

XX. Let’s move on to the next directory, .public

24

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 28: Play for Java v2 Meaph

The directory contains a few files already:public

README app conf project public images    favicon.png javascripts    jquery-1.7.1.min.js stylesheets main.css target

As you can maybe guess from its contents and its name, the directorypublic

contains resources that are served directly, without any processing. This is actuallywhat the second route we saw in section 2.3 does: it makes the contents of thisdirectory available as ; files that are available to the client directly.public assets

# Map static resources from the /public folder to the /assets URL pathGET /assets/*file controllers.Assets.at(path="/public", file)

Public assets are usually support files that are not actually your application.Things like images, stylesheets, JavaScript files and static HTML pages are allpublic assets. Public assets are not generated by you application, they’re just servedto the client.

Play adds some additional features to requests serving public assets. It addssupport for by providing ETag headers, and using gzip. It’scaching compressionimportant to note that the contents of the files are always served to the clientuntouched.

If you’re interested in certain files, such as Less stylesheets,pre-processingCofeeScript files or JavaScript files, be sure to read section 2.6.1 about compiled

. But first, let’s move on to the the directory.assets app

The directory is the most important directory of you application. It containsapp

your actual application code – that is, any part of your application that will need tobe compiled, such as your Java source files and view templates, which we’lldiscuss in a bit. When newly generated, the directory contains the followingapp

files:

2.5 Public assets

2.6 Application code

25

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 29: Play for Java v2 Meaph

app   controllers      Application.java   views   index.scala.html   main.scala.html conf project public target

The files that are there are responsible for generating the welcome page we sawwhen we navigated to in section the introduction in chapterhttp://localhost:9000/1.

There is one file, , that contains Java codeApplication.java

implementing the for generating the webpage. Classes that take abusiness logicHTTP request, run some logic on it, and return a HTTP result are called controllerclasses, which explains why they’re in the folder.controllers

There are two files, and template index.scala.html

, which are responsible for defining the HTML page. Anymain.scala.html

content that’s generated on the server and sent to the client in a HTTP body, suchas a HTML page, is called a , therefore, the files are in the folder.view views

The template files contain a template in Play’s Scala template syntax. Animportant aspect of Scala templates is that they’re actually compiled to regularclasses. This has all sorts of advantages, the most important of which arecompile-time syntax and type checking.

SIDEBAR You have to learn Scaladon’tWhile Play’s Scala templates contain, in fact, actual Scala code, thisdoes mean you have to learn or understand Scala. Any templatenotlanguage has structures you need to know to build your templates, andScala templates are no different. Once you know what you have to doto, for example, iterate over a collection, or insert a variable valuesomewhere, you know all you have to to use that feature. You don’thave to think of it as Scala if you don’t want to. Think of it as justanother template language.Now, if you happen to Scala, you will recognize the structuresknowused in the tags, and understand why they work the way they work. Butthe point is that you don’t to in order to use the template syntax,haveand enjoy all the benefits they bring.

26

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 30: Play for Java v2 Meaph

Another thing that’s important to note about the directory is that it’sapp

actually the root for all your source code, meaning that any subfolder willautomatically have to be a package, just like with any regular Java project.

You might be used to having your packages look more like a domain space,such as , but there’s actuallyorg.mycompany.myproject.mypackage

nothing that forces you to do that. It happens to be convention, and that conventionmainly exists for namespacing purposes, to prevent classes with the same namestepping on each other’s turf. Since you won’t be running two Play apps in thesame JVM at the same time, you don’t have to worry about that in your Play apps,so Play doesn’t follow that convention. That’s why your controllers are in the

package, your views in the package, and so on. Nice,controller views

concise and easy to follow.Now, let’s look at another cool feature in Play that also uses the directory:app

compiled assets.

We’ve seen what assets are in section 2.5, where we introduced assets as just filesserved to the client, but actually assets also be the result of compilation. Ofcancourse a CSS or JavaScript file doesn’t have to be compiled, but there are certaintools that generate them. Play has the option to pre-process assets before they areserved to the client, giving you more convenience and flexibility over these files.Out of the box, Play 2 comes with support for Less, CoffeeScript and Google’sClosure compiler. Using them is completely optional, of course, but Play makes iteasier for you to use these technologies if you want to.

The source files for compiled assets should be kept in your application’s directory. That directory is not auto-generated by Play, so create itapp/assets

if you want to use this feature.

Less is a dynamic stylesheet language that is compiled to CSS, offering a more5

powerful and flexible stylesheet language that is still compatible with any browser.Any file saved in the directory will be compiled into the.less app/assets

application’s folder, which means the result will be available as a regularpublic

public asset.

Footnote 5 m http://lesscss.org/

2.6.1 Compiled assets

LESS

27

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 31: Play for Java v2 Meaph

CoffeeScript is a programming language that compiles to JavaScript. It is6

generally considered a cleaner and more readable language than JavaScript, and isgaining popularity. Any file placed in the will be.coffee app/assets

compiled to the application’s folder, just like Less files.public

Footnote 6 m http://coffeescript.org/

If you’re not using CofeeScript, but JavaScript, you might want to use Google’s

Closure compiler (not to be confused with the programming language ‘Clojure’) .7

The Closure compiler analyzes your JavaScript code, and tries to make it run fasterand warns you about potential problems. It also makes your code smaller (this iscalled ), which will make it download and run faster. Just like Less andminifyingCoffeeScript, place any files you want to compile in the .js app/assets

directory and they will be compiled to ./public/

Footnote 7 m https://developers.google.com/closure/compiler/

Now that we know what all the directories and files are for, we’re going to editsome of them in a moment, and start implementing our actual PoC application. Ofcourse, you could edit the files with just a plain text editor. However, if you use aJava IDE such as Eclipse, IntelliJ or Netbeans, you’ll find that editing your sourcecode becomes a lot easier, and you’ll be more productive. One of the advantages ofusing a type-safe language like Java is that tools like IDEs can do a lot to makecoding faster and easier (and therefore more fun). Most IDEs offer features such asauto-completion, automated refactoring and static code analysis. In short, an IDEmakes your life easier.

Play makes it easy to import your applications into most well-known IDEs byincluding commands that will set up a project for you. Play comes with support for

Eclipse and IntelliJ IDEA . This does mean that you can’t just use any IDE8 notyou want, it just means that you have to set up the project in your IDE yourself.

Footnote 8 m TODO: check for netbeans support by the time the book is done

Eclipse is one of the most well-known and widely used Java IDEs. It’s open sourceand free to use. Here’s how you set up your application for Eclipse.

COFFEESCRIPT

JAVASCRIPT

2.7 Setting up an IDE

2.7.1 Eclipse

28

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 32: Play for Java v2 Meaph

Figure 2.2 A new Play application in Eclipse

First of all, you need to generate the Eclipse-specific files that instruct Eclipsehow to load your application and its dependencies, and how to build it. Playgenerates the necessary files for you when you run the commandeclipsify

from the Play console.

29

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 33: Play for Java v2 Meaph

Once these files have been generated, Eclipse will be able to recognize yourapplication’s directory as an Eclipse project, and you can import it directly. To doso, use the command under the menu in Eclipse’s menu bar. Whenimport FileEclipse asks you what you want to import, choose General > Existing Projects into

. On the next screen, click browse to select your application’s rootWorkspacedirectory, and Eclipse will recognize the project. Click the button, and you’refinishall done setting up your Eclipse project.

IntelliJ IDEA is a commercial IDE from JetBrains. It is open source, and thecommunity edition is free to use, with more powerful features available in the paid‘ultimate’ edition.

2.7.2 IntelliJ IDEA

30

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 34: Play for Java v2 Meaph

TODO: IntelliJ currently has support for Play 1. Check if this available for Play2 as well by the time the book is done. Or find some sort of generic SBT-basedsolution.

Figure 2.3 A new Play application in IntelliJ Idea

Play 2 can make an IntelliJ ‘project’ out of your application, but the model thatis part of this project can also be imported into any existing project you mighthave. To create the IntelliJ project, run the command from the Play 2idea

console.To open the project in IntelliJ, simply select from theFile > Open project…

menu bar, and choose the directory for your application.To import this module into your IntelliJ project, select fromFile > New Module

the menu bar, then select ‘Import existing module’, and browse for the .iml filePlay created for you. Click and your Play 2 application will be added toFinishyour IntelliJ project.

One of the most useful features in Java IDEs are their debuggers, which tap intothe JVM that’s running your application and allow you to pause code execution atany point (such a point is called a ) and inspect the state of yourbreak pointapplication.

2.7.3 Using a debugger

31

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 35: Play for Java v2 Meaph

To debug a Play application, you need to start it in debug code, and thenconfigure your debugger to use , which means that yourremote debuggingdebugger will connect to a JVM that’s already running, rather than the IDElaunching one and connecting to that.

To start Play in debug code, start it with the parameter. Play will telldebug

you which port to connect your debugger to, which is port 9999 by default:

~/hello play debugListening for transport dt_socket at address: 9999[info] Loading project definition from /Users/sietse/hello/project[info] Set current project to hello (in build file:/Users/sietse/hello/)

If you want to use Eclipse’s debugger with your Play application, you need toset up a new under the menu. Select debug configuration run Remote Java

and click the ‘new’ button to create a new remote debug configuration.ApplicationSet it to connect to your Play application on , by default on port 9999.localhost

To actually start debugging, select in the menu bar.Run > Debug

32

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 36: Play for Java v2 Meaph

To use IntelliJ’s debugger with a Play application, select Run > Edit from the menu bar, and then click the plus button in the upper leftConfigurations

corner. From the menu that pops up, select to create a new remote debugRemoteconfiguration. To start using your new configuration, select fromRun > Debug…the menu bar.

33

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 37: Play for Java v2 Meaph

Explaining how to use the debugger is beyond the scope of this book, but thisshould be enough to get you started debugging with Eclipse or IntelliJ.

In this chapter, we’ve created a new Play 2 Java project, and identified whatdirectories and files make up a Play application.

We’ve learned that compiled code goes under /app/, and that that includes any such as Less and CoffeeScript files. Static assets go in /public/ andcompiled assets

that /conf/ holds important configuration data, such as the routes file andapplication.conf.

We’ve also seen how to set up an IDE, and how to attach a debugger to arunning Play application.

In the next chapter, we'll start coding our example application.

2.8 Summary

34

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 38: Play for Java v2 Meaph

3This chapter covers:

In the previous chapter, we’ve introduced our example application: the paperclipwarehouse management system. Now that we know what we’re going to build, andhave our IDE all set up, it’s time to start coding.

In this chapter, we’ll start implementing our proof-of-concept (poc) application.

It will be a simple CRUD application, with data stored in-memory rather than in a1

database. We’ll evolve our poc application in later chapters, but this simpleapplication will be our starting point.

Footnote 1 Create, Retrieve, Update, Deletem

We’ll start by setting up a controller with some method, an link some URLs tothem.

A basic CRUD application

Installing and running Play 2

The contents of a Play application

Setting up an IDE and debugger

An introduction to all major Play concepts

Creating a small application

35

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 39: Play for Java v2 Meaph

In chapter 1, we edited the class, changing the default output andApplication

adding custom operations. The class is an example of a Application controller

class. Controller classes are used as a home for , which are theaction methodsentrypoints of your web application. Whenever a HTTP request reaches the Playserver, it is evaluated against a collection of rules in order to determine what actionmethod will handle this request. This is called the request, which isroutinghandled by something aptly named the , which, in turn, is configured usingrouterthe conf/routes file, as described in section XREF_play_8217_s_configuration_files. After the correct action method is selected, thatmethod executes the logic necessary to come up with a to return to the client,resultin response to the request. This process is illustrated in figure 3.1.

Figure 3.1 Requests routed to actions

The only requirement of a controller class is that it extends . It does have to be part of a specific package,play.mvc.Controller not

although it is convention to put controllers in the controllers package. Let’s createone for our product catalogue. Since we’re dealing with products, we’ll call it

. Create the class under the controllers package. Have itProducts Products

extend , like so:Controller

package controllers;

import play.mvc.Controller;

public class Products extends Controller {

}

3.1 Adding a controller and actions

36

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 40: Play for Java v2 Meaph

Now, an empty controller doesn’t do anything, of course. The whole purpose ofcontrollers is to provide action methods. An action method has to conform to thefollowing requirements:

it has to be public

it has to be static

it has to have a return type of (a sublcass of) Result

Let’s add some action methods to our controller. For our proof-of-conceptapplication, we’ll want to products in our catalogue, details for individuallist showproducts, and new and updated products. We’ll add actions for thesesaveoperations, but for now, we’ll make them return a special type of result; . A TODO

result signifies that the method is yet to be implemented. Add theTODO

corresponding actions, as shown in listing 3.1.

Listing 3.1 Adding action methods

package controllers;

import play.mvc.Controller;import play.mvc.Result;

public class Products extends Controller {

public static Result list() { return TODO; }

public static Result showBlank() { return TODO; }

public static Result show(Long ean) { return TODO; }

public static Result save() { return TODO; }

}

Now that we have some action methods, let’s give them URLs so that we canreach them.

List all products

Show a blankproduct form

Save a product

37

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 41: Play for Java v2 Meaph

In order to determine which action method will handle a given HTTP request, Playtakes the properties of that request, such as its method, url and parameters and doesa lookup on a set mappings called . Like we saw before, in section XREFroutes_play_8217_s_configuration_files, routes are configured in the routes file in yourapplication’s conf directory. Add routes for our new operation, as shown in listing3.2

Listing 3.2 adding routes for our product catalog

GET /products/ controllers.Products.list()GET /products/new controllers.Products.showBlank()GET /products/:ean controllers.Products.show(ean: Long)POST /products/ controllers.Products.save()

Now that we have some routes, let’s try them out. Start your application if it’snot already running, and point your browser at http://localhost:9000/products/. Youshould see the page shown in figure 3.2.

Figure 3.2 Play’s TODO placeholder at /products

If you see the TODO placeholder page, that means the controller, actionmethod and route are all correctly set up. Time to add some actual functionality.The first step is adding a class that will model our products.

3.2 Mapping URLs to action methods using routes

38

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 42: Play for Java v2 Meaph

In order to create a product catalog, we need a class to represent ‘a product’ in ourapplication. Such classes are called classes, since they model real-worldmodelconcepts.

We’ll keep our product model simple for now - an article number, name anddescription will do. For the article number, we’ll use an EAN code, which is a13-digit internationally standardized code. Create a class called . Put itProduct

in a new package called models. Again, there’s nothing about Play that requiresyou to put model classes in the models package, but it’s convention to do it thatway. Add the properties we just mentioned to your new class, and add aconstructor that sets them on instantiation, for convenience. Also add a defaultno-arg constructor, we’ll be needing that later. You’ll have a class as shown inlisting 3.3.

Listing 3.3 Our basic classProduct

package models;

public class Product { public Long ean; public String name; public String description; public Product() {} public Product(Long ean, String name, String description) { this.ean = ean; this.name = name; this.description = description; }

public String toString() { return String.format("%s - %s", ean, name); }

}

3.3 Adding a model and implementing functionality

3.3.1 Creating a model class

39

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 43: Play for Java v2 Meaph

NOTE Don’t be alarmed by public propertiesIf you’ve been a Java developer for some time, you’re probablysurprised that we choose to use public properties. You’re probablymore used to making properties private, and exposing them usinggetter and setter methods instead, creating a ‘Java Bean’. Don’tworry, we know what we’re doing For now, just bear with us.Everything will be explained in detail in chapter 5.

We’ve just created our first model class. In most cases, instances of these modelclasses are also stored in a database. To keep things simple, we’ll fake thisfunctionality for now by just maintaining a static list of products. Let’s create somedata now.

We’ll mock storage by using a static of s on the class,Set Product Product

and put some data in it in the class’ static initializer, as shown in listing 3.4.

Listing 3.4 Adding some test data

private static Set<Product> products;

static { products = new HashSet<Product>(); products.add(new Product(1111111111111L, "Paperclips 1", "Paperclips description 1")); products.add(new Product(2222222222222L, "Paperclips 2", "Paperclips description ")); products.add(new Product(3333333333333L, "Paperclips 3", "Paperclips description 3")); products.add(new Product(4444444444444L, "Paperclips 4", "Paperclips description 4")); products.add(new Product(5555555555555L, "Paperclips 5", "Paperclips description 5"));}

WARNING Never do this in a real applicationWhile having a static property serve as a cache for data is convenientfor this example, never do it in a real-world app. Since we’ll only beusing this in dev-mode, which has only 1 thread running bySet

default, we won’t run into any serious trouble. But when you try this inany environment with multiple threads, or even multiple applicationinstances, you’ll run into all sorts of synchronization issues. Dependingon the situation, either use Play’s caching features (chapter XX)instead, or use an actual database (chapter 5).

3.4 Mocking some data

40

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 44: Play for Java v2 Meaph

Now that we have some data, let’s also add some methods to manipulate thecollection of s. We’ll need methods to retrieve the whole list, to find allProduct

product by EAN and (part of the) name, as well as methods to add and removeproducts. Add the methods shown in listing 3.5. We’ll let their implementationsspeak for themselves.

Listing 3.5 Data access methods on the Products class

public static Set<Product> findAll() { return new HashSet<Product>(products);}

public static Product findByEan(Long ean) { for (Product candidate : products) { if (candidate.ean.equals(ean)) { return candidate; } } return null;}

public static Set<Product> findByName(String term) { final Set<Product> results = new HashSet<Product>(); for (Product candidate : products) { if(candidate.name.toLowerCase().contains(term.toLowerCase())){ results.add(candidate); } } return results;}

public static boolean remove(Product product) { return products.remove(product);}

public static void add(Product product) { products.add(product);}

Now that we have the plumbing for our products catalogue, we can startimplementing our action methods.

41

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 45: Play for Java v2 Meaph

We’ll start with the implementation for the method. Like we said before, anlist

action method always returns a . What that means is, it should return anresultobject with a type that is a subclass of . Those kind ofplay.mvc.Result

objects hold all information that Play needs to construct an HTTP response. AnHTTP result consists of a status code, a set of headers, and a body. The statuscodes indicate whether or not a result was successful, and indicates what theproblem is if it was not. Play’s class has a lot of methods toController

generate these result objects. So let’s go ahead and replace our result with aTODO

code 200 result, OK. To do this, just use the   method to obtain a new OKok()

result, like this:

Listing 3.6

public static Result list() { return ok();}

Now, if you were to try this out in a browser, you’d get an empty page. If youwere to check the actual HTTP response, you’d see that the reponse status code haschanged from to . The reason that our501 - Not Implemented 200 - OK

browser shows an empty page is that our response has no body yet. This makessense, since we didn’t put one in yet. To generate our response body, we want togenerate an HTML page. For this, we’ll want to write a template file.

Like we saw earlier in the chapter, a Play template is a file containing some HTMLand Scala that Play will compile into a class that we can use to render a HTMLpage. Templates go in your application’s views directory, and to keep things cleanand separated by functionality, we’ll create a products directory there. Next, createa file called list.scala.html, and put in the contents shown in listing 3.7.

Listing 3.7 list.scala.html

@(products: Set[Product])

@main("Products catalogue") {

<h1>All products</h1>

<dl>

3.5 Implementing the methodlist

3.5.1 The list template

42

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 46: Play for Java v2 Meaph

@for(product <- products) { <dt> <a href="@routes.Products.show(product.ean)"> @product.ean - @product.name </a> </dt> <dd>@product.description</dd> } </dl>

<a href="@routes.Products.showBlank()" class="btn"> <i class="icon-plus"></i> New product</a>}

When rendered, this template will product a page as seen in figure 3.3.

Figure 3.3 Our products listing

Without going into too much detail (see chapter XX for everything abouttemplates), let’s see what happens in the template.

The first line of the list template is the :parameter list

@(products: Set[Product])

With the parameter list, we define what parameters this template accept. Everyentry in the parameter list consists of a name, followed by a colon and the type ofthe parameter. So, in our example, we have one parameter called name, of type

, to represent the list of products we want to render. ThisSet<Product> 2

parameter list will be part of the method definition for this template’s render

method, which is how Play achieves type safety for its templates.

HOW THE TEMPLATE WORKS

43

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 47: Play for Java v2 Meaph

Footnote 2 In Scala syntax, generic type arguments are indicated using square brackets instead of angle brackets.m

Let’s take a look at the next line of code, which actually starts a block:

@main("Products catalogue") { ...}

With this code, we actually call another template, the one called . This ismain

the template at /app/views/main.scala.html, that Play created for us when wecreated the application. It contains some boilerplate HTML that we’ll wrap aroundall our pages, so we don’t have to worry about that any more. The code we write inthe block will end up in the tag of our rendered HTML page. This is how<body>

you can compose templates in Play, and we’ll see more of this in later chapters.The body of our code block is mainly just HTML, which will be included in the

rendered page verbatim. There’s just one bit of template code left – the bit thatiterates over our products list:

@for(product <- products) { ...}

This bit of code is comparable to a regular Java for-each loop: it iterates over acollection, and repeats the code it wraps for every element in it, assigning thecurrent element to a variable. So, in our example, it generates a pair of /<dt>

elements for every in our products list. Listing 3.8 shows the full<dd> Product

loop as a reminder.

Listing 3.8 loop generating the product descriptionsfor

@for(product <- products) { <dt> <a href="@routes.Products.show(product.ean)"> @product.ean - @product.name </a> </dt> <dd>@product.description</dd>}

The pieces of code in the loop’s body that start with an ’@’ are Scalaexpressions: the code that follows the @ is evaluated, and the result included in theoutput. In this case, we use it to print out properties of , and generateproduct

links to our action methods based on our routing configuration. For everythingabout routing, see chapter 6.

44

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 48: Play for Java v2 Meaph

Now that we have a template, all that’s left for us to do is gather a list of productsand render the template in our action method. Listing 3.9 shows how.list

Listing 3.9 Rendering the list template

...import views.html.products.list;

public class Products extends Controller { public static Result list() { Set<Product> products = Product.findAll(); return ok(list.render(products)); } ...

}

As you can tell from the imports in this example, the template/views/products/list.scala.html results in a class called

. This class has a static method called views.html.products.list list

, which, as your IDE can tell you, takes one parameter of type render

and returns an object of type . The parameter, of course, isSet<Product> Html

the one we defined at the top of our template, while the return type is determinedby the .html extension of the template filename.

The method on the template results in an HTML page, which we wantrender

to return to the client in the body HTTP response. To do this, we wrap it in a object, by passing it to the method.Result ok

Time to try out our code. Navigate to http://localhost:9000/products/ and youshould see a list as in figure 3.4.

RENDERING THE TEMPLATE

45

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 49: Play for Java v2 Meaph

Figure 3.4 Our products listing

Now that we can see our list of products, let’s continue implementing features.

A static product catalogue isn’t very useful. We want to be able to add products tothe list. We will need a form, for that, so create a new template calledshow.scala.html at /app/views/products. We’ll create a form that will work both forcreating new products as well as editing existing ones. The template is shown inlisting 3.10.

Listing 3.10 The products form template

@(productForm: Form[Product])@import helper._@import helper.twitterBootstrap._

@main("Product form") { <h1>Product form</h1> @helper.form(action = routes.Products.save()) { <fieldset> <legend>Product (@productForm("name").valueOr("New"))</legend> @helper.inputText(productForm("ean")) @helper.inputText(productForm("name")) @helper.textarea(productForm("description")) </fieldset> <input type="submit" class="btn primary"> }}

As you can see on the first line of the template, this template takes a parameter, just like our template took a Form<Product> list

3.6 Adding the product form

46

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 50: Play for Java v2 Meaph

parameter. But what’s this class? is what Play usesSet<Product> Form Form

to represent HTML forms. It represents name/value pairs that can be used to builda HTML form, but it also has features for input validation, error reporting and databinding. Data binding is what makes it possible to convert between HTTP (form)parameters and Java objects and vice versa.

Let’s see how these forms work. First, we need to create one to pass to thetemplate. That’s as easy as calling the method in our action method. The form

method takes a class as a parameter, to tell it what kind of object the form isform

for. Since a product form is always the same, and we’re going to use it in a fewplaces in the controller, we might as well create a constant for it on theProducts

class, like so:

private static final Form<Product> productForm = form(Product.class);

Now that we have an empty form, it’s easy to pass it to the template. Implementthe action method as shown here:showBlank

public static Result showBlank(){ return ok(show.render(productForm));}

With this action method implemented, you can see the form athttp://localhost:9000/products/new . It should look like figure 3.5.

3.6.1 Constructing the form object

47

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 51: Play for Java v2 Meaph

Figure 3.5 The product form

Let’s see how this template creates the HTML form.

Now that we have the form object available in our template, let’s see how we makean actual HTML form from it. At the top of the template, you can see how weimport two helpers:

@import helper._@import helper.twitterBootstrap._

These helpers are there to help us generate HTML. The first one importsgeneric HTML helpers, and the second one makes the generated HTML fit theTwitter bootstrap layout. We first use one of these helpers when we start the form:

@helper.form(action = routes.Products.save()) { ...}

The helper generates a HTML element. The form <form> action

parameter tells it where the form should be submitted to. In our case, that’s the method on our controller. Play will turns this into a save Products action

attribute with the correct URL value for us.Of course, a form is not much use without any fields. Let’s see how those are

3.6.2 Rendering the HTML form

48

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 52: Play for Java v2 Meaph

constructed.

Our form contains a single fieldset, which is created using regular HTML. Thevalue for the fieldset’s element is interesting enough to take a closer looklegend

at. It starts of with regular text, ‘Product ’, but then we use the form object toconstruct the rest of the value:

@productForm("name").valueOr("New")

Here, we request the form field ‘name’, by calling productForm("name")

. This object is of type , and represents the form field for the name3 Form.Field

property of the form. To get the value, we could simply call the method onvalue

the field. However, since we don’t know there is a value for this field, we use theif method, which allows us to specify a default value to use in case thevalueOr

field has no value. This saves us checking for a value manually, which saves a lotof messy, verbose code in our template.

Footnote 3 ‘productForm("name")’ is actually short for productForm.field("name").m

The next few lines in our template actually render input elements – one for eachproperty of our class:Product

@helper.inputText(productForm("ean"))@helper.inputText(productForm("name"))@helper.textarea(productForm("description"))

When our template is rendered, these lines are rendered as shown in listing3.11.

Listing 3.11 Rendered input elements

<div class="clearfix " id="ean_field"> <label for="ean">ean</label> <div class="input"> <input type="text" id="ean" name="ean" value="" >

<span class="help-inline"></span> <span class="help-block"></span> </div></div>

<div class="clearfix " id="name_field"> <label for="name">name</label> <div class="input">

3.6.3 Rendering input fields

49

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 53: Play for Java v2 Meaph

<input type="text" id="name" name="name" value="" >

<span class="help-inline"></span> <span class="help-block"></span> </div></div>

<div class="clearfix " id="description_field"> <label for="description">description</label> <div class="input"> <textarea id="description" name="description" ></textarea>

<span class="help-inline"></span> <span class="help-block"></span> </div></div>

With just 3 simple lines of code, we’ve generated all that HTML! And becauseof the bootstrap helper, it doesn’t look bad, either.

The final line of our template’s form adds a regular HTML submit button, andwith that, our form is ready. When you try it out, the form will submit to ourunimplemented method, so it doesn’t do much yet. Let’s take care of thatsave

now.

When you submit the product form in the browser, the form gets submitted to theURL specified in the attribute of the HTML element, which, inaction <form>

our case, ends up at the action method of our application. It’sProducts.save

now up to us to transform those HTML form parameters into a instance,Product

and add it to the product catalog. Luckily, Play has some tools to make this jobeasy.

When we created the object in the previous section, we used it to create aForm

HTML form based on the class. But Play’s s work the other wayProduct Form

around, too. This reverse process is called .bindingPlay can bind a set of name/value combinations, such as a , to a class thatMap

has properties with the same names. In this case however, we don’t want to bind amap, but we want to bind values from the request. While we could obtain a ofMap

the name/value pairs from the HTTP request, this situation is so common that the class has a method to do this: . This will return a new Form bindFromRequest

3.7 Handling the form submission

50

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 54: Play for Java v2 Meaph

object, with the values populated from the request parameters. So, to obtainForm

a from our form submission, and add it to the catalog, we can write theProduct

following code:

Listing 3.12 Product binding

public static Result save() { Form<Product> boundForm = productForm.bindFromRequest(); Product product = boundForm.get(); Product.add(product); return ok(String.format("Saved product %s", product));}

When you try out the form now, you’ll get a simple text message informing youof the successful addition of the product. If you then check the catalogue listing wemade in section 3.5, you can verify that it worked.

But, our current implementation is not very nice. The user is free to enter anon-numeric ean code, for example, which will cause the binding to fail. Also, thetext message isn’t very nice. It would be a lot nicer to re-render the form with anerror message on failure, and show the product listing with a success message ifeverything was correct. Listing 3.13 shows a different version of that hassave()

that functionality.

Listing 3.13 A better implementationsave

public static Result save() { Form<Product> boundForm = productForm.bindFromRequest(); if(boundForm.hasErrors()) { flash("error", "Please correct the form below."); return badRequest(show.render(boundForm)); } Product product = boundForm.get(); Product.add(product); flash("success", String.format("Successfully added product %s", product));

return redirect(routes.Products.list());}

In this version of our implementation, we use the functionality ofvalidationPlay’s forms. On the second line of our method, we ask the if there are anyForm

errors, and if there are, we add an error message and re-render the page instead. Ifthere are no errors, we add a success message and redirect to the products listinstead.

51

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 55: Play for Java v2 Meaph

The error and success messages are not visible yet. We have added them tosomething called the . Flash scope is place where we can store variablesflash scopebetween requests. Everything in flash scope is there until the following request,and is then deleted. It’s ideal for success and error messages like this. But we stillneed to render these messages.

Since messages like these are useful throughout the application, let’s add themto the main template, because that’s what every page extends. That way, everypage will automatically display any messages we put in flash scope. Add the linesshown in listing 3.21 to the start of the element in<body>

app/views/main.scala.html.

Listing 3.14 Displaying flash success and error messages

@if(flash.containsKey("success")){ <div class="alert alert-success"> @flash.get("success") </div>}

@if(flash.containsKey("error")){ <div class="alert alert-error"> @flash.get("error") </div>}

Now, try out the form. Load the form at http://localhost:9000/products/new ,and try to enter a non-numeric EAN code. You should see a page as in figure 3.13.

Figure 3.6 Validation errors in our form

There’s a lot more possible using form validation, but for now, this is enough.

52

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 56: Play for Java v2 Meaph

You can learn all about forms and validation in chapter XX.Now that we have our form working, we can actually reuse it to edit existing

products. To do this, we need to implement the method as in listing .show

Listing 3.15 Implementing the methodshow

public static Result show(Long ean) { final Product product = Product.findByEan(ean); if (product == null) { return notFound(format("Product %s does not exist.", ean)); }

Form<Product> filledForm = productForm.fill(product); return ok(show.render(filledForm));}

As you can see, it doesn’t take a whole lot of code to turn a ‘new product’ forminto a ‘product edit’ form. This method takes an EAN code as a parameter from theURL, as we defined in the routes file in section 3.2. We then look up the productbased on EAN. If there is no product with that EAN, we return a 404 - Not

error.Found

If we find a product, we create a new object, pre-filled with the datadid Form

from the product we found. We use the method on our existing empty formfill

object for that. It’s important to note that this does fill in the existing form, butnotit creates a new form object on the existing form.based

Once we have the form, all that remains is to render the template and return the’ok’ result, just as in .showBlank

Now, this action method is complete, and now the links in the product listing allwork correctly, and the functionality for our proof-of-concept application iscomplete.

In this chapter, we’ve implemented a simple proof-of-concept application. Weadded all the CRUD functionality, with a datastore in memory. We’ve started witha with some basic , and linked them to URLs by settingcontroller action methodsup Play’s system. We then introduced some , and addedrouting view templatessome with .forms validation

This chapter was an quick introduction to all the core concepts of Play. Alltopics in this chapter will be explained in detail in later chapters, but now youknow have the general idea of the most important concepts. You’ve also had a taste

3.8 Summary

53

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 57: Play for Java v2 Meaph

of what it means that Play is type safe. If you followed along with the exercises,and you made an occasional mistake, you’ve probably also seen how soonmistakes are spotted because of the type safety, and how useful Play’s errormessages are when a problem is found.

54

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 58: Play for Java v2 Meaph

5This chapter covers:

In the previous chapter, we’ve seen the basic situation and requirements for ourpaperclip warehouse application. Now it’s time to start putting this knowledge towork in code. Since we have a pretty good idea of what concepts we have in thewarehouse, we’ll start by defining a data model. The data model will be ourrepresentation of objects and concepts within the warehouse’s processes.

SIDEBAR First things first?While it seems to be convention in most application frameworks to startwith the data model, Play doesn’t dictate where you start developingyour application; if you want to start developing your views orcontrollers first, Play will not fight you. Feel free to work in any orderyou like!

We’ll start this chapter by developing the data model as Java classes in theapplication we created last chapter, and then we’ll make it possible to store data to

Models and persistence

Defining datamodels

Persisting data

Mapping your model using JPA annotations

Querying data using Ebean

55

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 59: Play for Java v2 Meaph

a relational database using the persistence facilities that come with Play. Finally,we’ll explore some alternative persistence options, such as NoSQL databases andcloud-based data storage.

But first, we’ll define our data model.

The most basic requirement of our warehouse application is keeping track of whatstock items are in our warehouse, and what kind of product each item is. Acommon trick for creating a data model is taking a use case, and writing down allthe nouns, and what the relationships between these nouns are. If we apply therequirements from the previous chapter, we get the model shown in figure 5.1.

Figure 5.1 The data model representing our warehouse

A data model can be seen as a representation of a real-world concept in code.Object oriented languages are very suitable for this. A key aspect of objects is thatthey group data and behavior in a single entity. However, for our current datamodel, we’re only interested in grouping data – there’s no behavior we want tocapture yet. Java beans are exactly this kind of object; they model state, but notbehavior. They’re a collection of private fields, accessible through instancemethods called getters and setters.

However, a typical Java bean is a pretty dumb piece of code, with tons of

5.1 Modeling the real world in code

56

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 60: Play for Java v2 Meaph

unnecessary boilerplate code. If you think about it, most Java beans are just privatefields with simple getters and setters. Java beans are so full of boilerplate code thatthey can mostly be generated by any IDE worthy of the name.

The main reason Java classes, and Java beans in particular, are often given getterand setter methods is to encapsulate data and hide the internal representation of anobject.

The difference between calling a method on a object,getName() Person

and accessing its name field directly is the the difference between asking a personfor their name and accessing their birth certificate and reading the name on it. Theformer gives the person whose name we want to know a lot more control than thelatter, and the latter is also possibly exposing a lot more information than thatperson might choose to give. Also, we might just destroy the birth certificate. Itdoesn’t even matter whether we do it unintentionally or on purpose.

Now consider a person wearing a name tag – the name is there, clearly visiblefor everyone, not giving any more information than that, and it’s not modifiable.The fact that that person a name also isn’t exposing anything about the personhaswe don’t already know – a person always has a name, you could say it’s part oftheir public interface. In this case, asking the person for their name just seems silly.This situation is similar to having a class with a name field that is markedPerson

both and .final public

Let's see what all this looks like in actual code. Listing 5.1 shows the situationwhen using a getter.

Listing 5.1 with Person getName()

public class Person { private final String name; public Person(String name) { this.name = name; } public String getName() { return name; }}String name = new Person("John Doe").getName();

In this example, we define a field, but access to it is delegated through the method. So we "ask" the for its name, using the gettergetName() Person

a private name field

the correspondinggetter

"asking" thePerson object forits name

5.1.1 The reasons for getters and setters

57

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 61: Play for Java v2 Meaph

method.Figure 5.2 shows the same class, but implemented using a public field.

Listing 5.2 with a public propertyPerson name

public class Person { public final String name; public Person(String name) { this.name = name; }}String name = new Person("John Doe").name;

In this example, we expose the field directly. Now, the client client just readsthe name field directly. We've achieved the same result as in the previous example,but with less code.

The problem with just providing public field access to object properties,however, is that we don’t get to change our minds. Once we expose a field, it’s partof that object’s public API, and we should support it forever, or risk breaking clientcode that depends on it. For example, if we introduce a public name field, and laterdecide we want to “lie” about the name of our , we can’t, because itsPerson

internal state is exposed for the world to see, and our client code depends on itbeing there. This is why it’s very common to see Java classes with private fields,and corresponding getters that simply return the values of the fields, as a way offuture-proofing the class’ API.

Another good reason for getters and setters is that they are part of the JavaBean

specification, which offers a standardized way to expose private properties1

through methods. Many tools require this, including Ebean, which we’ll cover laterthis chapter. Tools that depend on the JavaBean convertion just won't work onclasses without getters and setters.

Footnote 1 http://docs.oracle.com/javase/tutorial/javabeans/m

While the case for getters and setters is strong, the downside is that theygenerate a lot of noise: a simple field with both a getter and a setter requires aroundseven lines of code extra (depending on your code formatting convention). Whilethis may not seem like much, the noise adds up if you have a class with lots offields, plus you have to remember to generate or write the correct methodwhenever you introduce a new field. Wouldn’t you rather focus on something else?

a public name field

58

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 62: Play for Java v2 Meaph

Play helps you eliminate all this boilerplate code where you’d normally write asimple getter and setter, and allows you to just use public fields whenever youdon’t require special logic you’d put in a getter and/or setter.

Don’t worry though, tools you use still get to use your model classes likeJavaBeans: Play uses a cool trick called "byte code enhancement" to add gettersand setters right after your original code is compiled, and then silently rewrites allyour client byte code to use the generated getters and setters. However, if youchange from field access to getter/setters, or the other way around, you'll find yourcode no longer compiles. This is because the bytecode enhancement takes place

your class is compiled, which means it has to actually compile first.afterThis means that if you ever change your mind about using getters and setters,

you'll have to rewrite your client code. Fortunately, all IDE’s will help you do thatautomatically, and if you do happen to miss an occurence, you'll get acompile-time error informing you. So it's not that big a deal, as long as its in yourapplication. Do think long and hard about choosing either approach if you everdecide to export and re-use a class of your application, such as whenoutsidewriting a Play module, or sharing your datamodel between applications. Breaking apublic interface is not cool.

SIDEBAR Pay no attention to the man behind the curtainThe byte code enhancement Play does to transparently add getters andsetter is an example of Play "magic"—there’s things going on behindthe scenes that are not immediately obvious from looking at the code,but the effects are there. It’s arguable that this is a desirable situation,but in practice it turns out that the pros often outweigh the cons.There used to be a lot more of "magic" like this in Play 1.x, but in Play2, this is the only thing that was carried over from Play 1. You don’thave to use it if you don’t want to, you can just create your own gettersand setters and Play won’t touch your classes.

Since we have the basic relational model, let’s fill in the details directly in Java.See figure 5.2 for a reminder of what our complete model looks like.

5.1.2 Let Play eliminate some noise for you

5.1.3 Creating our classes

59

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 63: Play for Java v2 Meaph

Figure 5.2 A reminder of our data model

Create the classes shown in listing 5.3 in the models package under theapplication we created last chapter (or start from scratch, if you want):

Listing 5.3 Our basic data model, represented in classes.

public class Product { public Long ean; public String name; public String description;

public String toString() { return name; }}

public class Warehouse { public String name; public List<StockItem> stock = new ArrayList<>();

public String toString() { return name; }}

public class StockItem { public Warehouse warehouse; public Product product; public Long quantity;

An EAN is aninternationalproduct number

Note that thesefields arerelationships

60

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 64: Play for Java v2 Meaph

public String toString() { return String.format("%d %s", quantity, product); }}

You application directory should now look like listing 5.1.

warehouse |- app |- controllers |- Application.java |- models |- Product.java |- StockItem.java |- Warehouse.java |- views |- conf |-public |-test |-db

Okay, let’s start using our model. We’ll create an object hierarchy using thismodel, and output some properties as a text response in the browser. In yourapplication, you’ll find the class in the controllers package. OpenApplication

it in your IDE, and change the method as shown in listing 5.4.index()

Listing 5.4 Using our model in the methodindex

import models.*;import play.mvc.*;import java.util.*;

public static Result index() { Warehouse warehouse = new Warehouse(); warehouse.name = "My Warehouse";

Product product = new Product(); product.name = "Stainless steel paperclips, small, 1000pcs"; product.ean = 1234L; product.description = "1000 blue paperclips.";

StockItem item = new StockItem(); item.quantity = 15L; item.product = product;

item.warehouse = warehouse; warehouse.stock.add(item);

List<String> output = new LinkedList<String>();

This class wasgenerated by Play.We’re going to editit next.

61

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 65: Play for Java v2 Meaph

output.add(format("My warehouse is called '%s'", warehouse)); output.add(format("It contains %d items", warehouse.stock.size())); output.add(format("The first is: %s", warehouse.stock.get(0)));

return ok(output.toString());}

set the relationship at both endsnavigation of the object hierarchy

In this example, we first create relationship between a warehouse and a stockitem ( ). To then get the information we want out of the object hierarchy, wenavigate it by accessing the properties we're interested in ( ).

Since we changed the method that generates the default welcome page, we canjust point a browser to to run our code. The browser willhttp://localhost:9000/show the following output:

[My warehouse is called 'My Warehouse', It contains 1 items, The first is: 15 Stainless steel paperclips, small, 1000pcs]

Congratulations, you have a working data model! Don’t worry too much aboutthe output to browser too much yet, we’ll talk about view templates for an entirechapter, later.

Now that we have our data model, and we know how to use it in our controllersand views, it’s time to start thinking about storing the data we collect.

Having all this data is very useful, but currently all data we build up during arequest is lost as soon as we finish handling a request. Therefore, we’ll want to

this data. We’ll be using a tool called to save our objects to apersist Ebeandatabase. Although other options are available, a database is the most commonsolution.

The term ‘database’ deserves a little explanation. While a database is technicallyany kind of data store, when developers say ‘database’ they usually mean a

database, which is a very specific kind of database. I’m sure you haverelationalused one before, but here’s a quick recap so we’re on the same page.

The most defining aspect of relational databases is that they store their data intables, which will have columns of specific data types, and which contain rows of

5.2 Persistence and Object Relational Mapping (ORM)

5.2.1 About relational databases

62

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 66: Play for Java v2 Meaph

data. Contrary to what the name suggests, relational databases don’t actually model

relations between tables . There are a few tricks that most databases implement to2

help cope with the lack of these relations. For example, you can force that thevalue of a certain column is present in another table’s identifying column (its

), which you can use to keep your data consistent when using primary key JOIN

clauses when querying for data. This relationship isn’t a very strong relationshiphowever, since the records aren’t linked together—it’s just a trick to lookactuallyup data that is related. It just happens to be a trick the database is optimized toperform.

Footnote 2 m the name comes from the mathematical concept of a relation. We’re just calling them tables.

An object hierarchy, on the other hand, actually relationships between itshasentities. One object can ‘have’ other objects, and that relationship can go bothways (a warehouse has stock items, but a stock item has a warehouse as well).Another concept from the object oriented world, that you generally won’t find in adatabase, is inheritance. Inheritance is actually just a different kind of relationship.Uniting these two different views on data structures is a challenge when using anobject oriented language with a relational database.

Although there’s mismatches between the OO world and the relational world, it isnot impossible to map objects to databases and vice versa. This process is called

(ORM). There are many tools that offer ORM for Java,Object-Relational Mappingbut the standardized one is the Java Persistence API (JPA). Another well-knowntool for this is Hibernate, and Hibernate can actually also serve as a JPAimplementation. If you’ve done anything database-related in Java, you’ve probablyused them, or at least heard of them.

SIDEBAR Summarizing the relation between databases and objectmodels

(Relational) Databases and Object models are fundamentally different.

They can be mapped onto each other, this is called Object-Relational, or ORM.Mapping

The most common Java standard for this is JPA.

Because of some mismatches between Play and JPA, Play comes withEbean instead.

5.2.2 Bridging the relational world and the OO world

63

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 67: Play for Java v2 Meaph

JPA allows you use annotations to specify the mapping of classes and fields totables and columns, respectively. It also allows you to define relationships betweenclasses. Any class mapped to the database is referred to as an , and we’ll beentityusing the same term from now on. In addition to mapping entities, JPA alsospecifies an API for saving and updating entities, managing transactions, and ofcourse querying the database for entities.

JPA has more or less become the default persistence API in the Java ecosystem,particularly in the JEE world. However, while Play doesn’t prevent you from usingJPA and/or Hibernate (or any other persistence solution, for that matter), it isn’t thedefault solution. This is because a big part of the JPA spec is based on managingentity state across e.g. requests, which is something Play has no use for, due to itsstateless nature, which we discussed in chapter X. Instead Play comes with adifferent ORM framework: Ebean.

Ebean is an ORM framework that takes different approach to managing entitiesthan most other ORM tools, such as JPA. The main difference, and this is whatmakes it a good match for Play, is that it has a API. Don’t worry toosessionlessmuch about what that means for now, but if you’ve used JPA before, you’ll noticethat you’ll spend a lot less time on managing entity state. If you haven’t used JPAbefore—congratulations, you won’t ever have to worry about what it means to‘refresh an entity’, or what the difference between and ‘attached’ entities and‘detached’ entities.

There is one aspect of JPA that Ebean borrows: the annotations for mappingentities. When using Ebean, you map entities exactly the same way as JPA. Let’ssee how this works.

TIP Reuse your existing JPA entity classesBecause Ebean uses regular JPA annotations, you can easilyre-use existing model classes. This can be extremely useful,especially when you’re writing a Play version of an existing JEEapplication.

5.2.3 Introducing Ebean

64

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 68: Play for Java v2 Meaph

NOTE Skip ahead if…If you already know how to map entities using JPA, you could skipahead to the next section.

When mapping classes to the database, you have to instruct the ORM tool, Ebeanin this case, what data in the object model goes where in the database. You do thisby mapping to , and to . You also need to flag a classclasses tables fields columnsas an , telling the tool that this is a class you want to use as part of the dataentitymodel you are mapping. We’ll do all this using annotations from JPA (found in thejavax.persistence package).

In addition to mapping the class, it’s a good idea to let our entity class extendPlay’s class. The model class will take some of the work off your hands,Model

adding some convenience methods to the entity, which we’ll discuss later in thischapter.

Anything stored in a database also needs some way to it. This is calledidentifyits . While we could use a field on the entity that’s guaranteed to beprimary keyunique (this is called a ), such as the EAN field on our class,natural key Product

it is often considered good practice to have a field specifically for this purpose(called a ). Therefore, we’ll introduce a field called id to oursynthetic key Long

entities, and annotate it with to indicate that we want to use it as the identifier@Id

for the class.Let’s start with the simplest case, one without relationships – the Product

class. As you can see in figure 5.3, the class itself owns no relationships.

5.3 Mapping basic entities

65

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 69: Play for Java v2 Meaph

Figure 5.3 Focus on the Product class

To map the class like figure 5.3, make the changes as shown belowProduct

in listing 5.3.

Listing 5.5 Mapping the classProduct

import javax.persistence.*;import play.db.ebean.Model;

@Entity public class Product extends Model {

@Id public Long id;

public Long ean; public String name; public String description; }

Add this annotation to flag this class as an entity.Extend the Model class for convenience.Introduce the id field.

66

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 70: Play for Java v2 Meaph

… and that’s all there is to it. We’re going to try it out in a minute, but first,let’s configure Play to use a database and tell Ebean where to look for entities.

We’ll use H2, a light-weight DBMS that comes bundled with Play. The nice thingabout H2 is that is has an "embedded" mode, which means it will load itselfon-demand, in the same JVM as Play runs in. It can also create databases inmemory on-demand, making it ideal for use during development, where you justwant to experiment with the database and don’t care about the data being keptaround.

Play’s configuration contains default settings for using H2 and Ebean, butthey’re commented out since not all applications require persistence. So, open upthe file conf/application.conf in your application’s directory, and find anduncomment the following lines:

db.default.driver=org.h2.Driver #Adb.default.url="jdbc:h2:mem:play" #Adb.default.user=sa #A...ebean.default="models.*" #B

#A Here we tell Play’s DB system to use H2…#B … and here we enable Ebean for our models package.Before we test if everything works, let’s review what we’re doing. In the

beginning of the chapter, we defined our data model using Java classes, whichrepresent our real-world concepts in code. It allows us to build a representation ofthe warehouse state in the JVM memory. Now, we want to store our data insomething more durable, we want to it in a database. Where Java usespersistobjects and method calls, databases store data in tables and are accessed throughSQL. To bridge the gap between the Java and SQL world, we’re ourmappingclasses to the database, using a kind of tool called ORM. Our ORM tool of choiceis Ebean.

The database server (also called a DBMS) we’ll use while developing ourapplication is H2. This is because of the flexibility it offers, which is also thereason it comes bundled with Play. When moving your app to production, you’reprobably going to swap it out with another DBMS, such as MySQL, PostgresQL,Oracle, which are the most well-known options. Ebean has support for most majorDBMSes, but if you’re worried about compatibility be sure to check the Ebeandocumentation.

5.3.1 Configuring Ebean and the database

67

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 71: Play for Java v2 Meaph

Figure 5.4 illustrates the architecture we just described.

Figure 5.4 Persistence in Play 2 with Ebean and H2

Okay, now (re)load the page at , and see if ithttp://localhost:9000/showworked. Unfortunately, you'll probably see a page that looks like figure 5.5.

Figure 5.5 Play offering database evolution

Whoa. What happened? Well, while it may not look like it, this is Play beinghelpful. When we defined a database connection, we told Play to connect to a H2

database, which will be automatically created upon connection . However, what3

68

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 72: Play for Java v2 Meaph

was not automatically created was the database – that is, its structure; theschematables and column definitions. Play generated an SQL script for that, and is nowoffering to run it for you. This is called database , and we’ll see later howevolutionthis allows you to create incremental versions of your database schema. For now,go ahead and click . You should be greeted by the sameApply this script now!default welcome page we saw when we first ran the application.

Footnote 3 m this is actually an H2 feature, not a Play feature. This will probably not happen with otherDBMSes.

So, presumably, we now have a database with a table in it. But how can we check?Play, of course, has the tools you need. Open a new browser tab and go to

.http://localhost:9000/@dbThe web-application you now see is the H2 web console that Play deploys

automatically as long as we’re still in dev mode (which we will be until we’removing our application to production). It gives you an UI to the H2 database

server. The default connection settings should be OK , so click . You4 connectshould see a page like shown in figure 5.6:

Footnote 4 m It should match the connections string in application.conf

5.3.2 Inspecting the H2 database

69

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 73: Play for Java v2 Meaph

Figure 5.6 TODO: This screenshot is from Play 1, since Play 2 doesn't have this yet

If you look at the left-hand side, you’ll see our newly-created product table,including the columns we defined as properties in the entity class.Product

Now we know we have a database with a table matching our entity’s scheme,let’s put something in it.

Add the following line to the end of the method, rightApplication .index()

before the statement:return

...product.save();

return ok(index.render("Your new application is ready."));...

5.3.3 Saving our first entities

70

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 74: Play for Java v2 Meaph

It’s interesting to note that the method was provided by the save() Model

class. If you wanted to, you could be more explicit about what exactly is doing thesaving:

...Ebean.save(product);

return ok(index.render("Your new application is ready."));...

But there’s more benefit to using the class than just convenience: if youModel

were to switch persistence solutions to, say, Hibernate, the Play module providingthis will likely provide a class with the same interface, meaning that all you’d haveto change is the import statement, and not any actual body code. It’s also justconvenient to have the available anywhere you have an instance of anysave

entity. Therefore it’s recommended to always use the class.Model

SIDEBAR Preventing model anemiaThe class provides some common database-related methods, inModel

an effort to prevent you from ending up with something Martin Fowler

has dubbed an "Anemic Domain Model ". An anemic domain model is5

a model that has no behavior (methods), just state (fields, data). This isoften considered an anti-pattern, since the whole point of objectoriented programming is is to couple behavior and state.

Footnote 5 m

http://www.martinfowler.com/bliki/AnemicDomainModel.html

By providing the database operations with the entity classes, itbecomes possible to do a database operation anywhere you have an

, without having to "hunt" some other object or class thatentity instanceprovides that functionality. It’s important to remember that this doesn’thave to stop with the behavior provided by the Model class, though.When aiming for rich model classes, it’s a good idea to add anyfunctionality that operates on your entities to the entity classesthemselves, rather than a controller or utility class.Ultimately, it’s your choice whether you want a rich data model or onethat just serves as a container for data, but it’s wise to make that choiceconsciously.

Now, let’s see if everything works as expected: reload the page, and clickshow

the table in the database. Next, click the button to execute a "selectProduct Run

71

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 75: Play for Java v2 Meaph

all" query on that table. The result should be one row, representing the product youjust persisted, as seen in figure 5.7.

Figure 5.7 TODO: This screenshot is from Play 1, since Play 2 doesn't have this yet

If everything seems to have worked, let’s move on to the next entity, which willhave a relation to the class we just created.Products

Let’s start working on our class. Here’s a reminder of its role in theStockItem

model:

5.4 Mapping relationships

72

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 76: Play for Java v2 Meaph

Figure 5.8 Focus on the StockItem class.

In our model, the class has two relationships: one to ,StockItem Product

and one to . Let’s ignore the warehouse for now, and focus on theWarehouse

reference to . In our warehouse’s product catalog, we’ll store many Product 6

different kinds of products. Red paperclips, blue paperclips, etc.

Footnote 6 m Let’s assume "Many" actually means "more than one"

In our physical warehouse, we’ll store many batches of those products, whichwe called a "stock item". For example, suppose the product catalogue has an entry"Box of 1000 blue paperclips", and we know about three pallets with thesepaperclips, each holding 500 boxes. One pallet is currently in warehouse A, and theother two are warehouse B. So we have three stock items in total.

Now, each stock item will represent the stock of exactly productindividual onefrom the product catalogue. This means the stock items have a "many-to-one"relation to their product. The opposite is also true – each product is potentiallyreferenced by stock items, so the product has a "one-to-many" relationship tomanythe stock items. This concept is illustrated in figure 5.9

73

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 77: Play for Java v2 Meaph

Figure 5.9 The relationship between `StockItem`s and `Product`s

In a relational database, a one-to-many relationship is usually modeled as acolumn on the "many" side (in this case, the stock item) pointing to the ID of arecord on the "one" side (such as the product). Whenever a stock item is retrievedfrom the database, that ID can be used to retrieve the correct row from the productstable, if needed. The ID used to point to the primary key of another table is called a

. This is illustrated in figure 5.10.foreign key

74

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 78: Play for Java v2 Meaph

Figure 5.10 The One-to-Many database relationship

So, let’s map the class. Add the annotation to the StockItem @Entity

class, and have it extend . In the previous example, the StockItem Model

class, we didn’t add any annotations to the fields of the class. This isProduct

because all its fields can be stored in the database directly – there’s no relationshipinvolved. In the class, we have only one such field; the quantityStockItem

field, which is a that maps neatly to the SQL type, which EbeanLong number

can automatically map.The other field, however, is our own class. We need to tell EbeanProduct

that this is a reference to another entity, and of relationship it is. In thiswhat kindcase, as we saw before, has a relationship to .StockItem many-to-one Product

Therefore, we flag this field with the JPA annotation, like shown in@ManyToOne

listing 5.6.

Listing 5.6 Mapping the - many-to-one relationship.StockItem Product

5.4.1 Mapping a one-to-many relationship

75

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 79: Play for Java v2 Meaph

import javax.persistence.ManyToOne;

@Entitypublic class StockItem extends Model {

public Warehouse warehouse;

@ManyToOne public Product product; public Long quantity; }

Time to persist our product, this time including its member: inStockItem

our method, call the method on the stock item.Application.index save()

See listing 5.7.

Listing 5.7 Saving the StockItem and its relationship.

...

StockItem item = new StockItem(); item.quantity = 15L; item.product = product; item.warehouse = warehouse; warehouse.stock.add(item);

product.save(); item.save();

...

Reload the page in the browser, and Play will offer to update your database foryou. Go ahead and apply the update.

WARNING Be careful when applying evolutions on production databasesPlay’s evolution mechanism checks your database schema against theschema it expects, and offers to make changes to the database if thisthe two don’t match. This can involve removing columns, or even entiretables, causing . Be very careful when applying evolutionsloss of dataon a database that has data you care about!

Now, we should have a new table for our stock items, containing a single rowwith the stock item we just saved. Let’s check it out in the H2 console, you shouldsee results similar to figure 5.11

Ignore this relationfor now, we’ll mapit later

add this line

76

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 80: Play for Java v2 Meaph

Figure 5.11 Looking at the stockitem table in H2 console.

Now that we’ve seen how to map a one-to-many relationship, what about theother side, the many-to-one? Well, the class is a good candidate for this.Product

When we have an instance of , we can already tell what product it’sStockItem

for. But when we have a , we can’t tell which stock items reference it.Product

To do this, we have to make the relationship .bi-directional

Mapping the "many" side on a bidirectional many-to-one relationship doesn’treally anything in the database: the information about the relationship is alreadystored, in the table that makes up the "one" side of the relationship:

5.4.2 Making the one-to-many relationship bi-directional

77

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 81: Play for Java v2 Meaph

Figure 5.12 A One-to-Many database relationship

This means that all that has to happen to retrieve stock items belonging to acertain product, is changing the query to include the stock items that have a theproduct’s ID stored in their column.product_id

So, let’s tell Ebean how to retrieve the objects. First, we need aStockItem

field to store these in, so add a field to the class.List<StockItem> Product

All we need to do now is mark it as a relation, just like we did withone-to-manythe many-to-one field on : annotate it with . However,StockItem @OneToMany

since the class is the side that persists the relationship, we need toStockItem

indicate what property on the class holds the relationship we’reStockItem

mapping. We do this using the mappedBy attribute on the annoation like in listing5.8

Listing 5.8 Making the - relationship bi-directionalProduct StockItem

import javax.persistence.ManyToOne;...

@Entity

78

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 82: Play for Java v2 Meaph

public class Product extends Model {

@Id public Long id; public Long ean; public String name; public String description;

@OneToMany(mappedBy="product") public List<StockItem> stockItems;}

Now, whenever you retrieve a instance from the database, you’llProduct

have access to its stockItems as well.The relationship between and is another example ofWarehouse StockItem

a one-to-many relationship. Let’s go ahead and implement it as in the listingsbelow. The class should look like listing 5.9:StockItem

Listing 5.9 StockItem.java

@Entitypublic class StockItem extends Model {

@Id public Long id;

@ManyToOne public Warehouse warehouse;

@ManyToOne public Product product;

public Long quantity;

}

And the class should look like listing 5.10:Warehouse

Listing 5.10 Warehouse.java

@Entitypublic class Warehouse {

@Id public Long id;

public String name;

@OneToMany public List<StockItem> stock = new ArrayList<StockItem>(); }

79

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 83: Play for Java v2 Meaph

Our warehouse class doesn't really store a lot of information about it. Let's addsome information to it.

Let's add a little more information to our warehouse. We need to know where onthe planet it is, so we know where our items are – we need an address. We couldadd a bunch of properties to the warehouse class, like in listing 5.11:

Listing 5.11 Adding address properties to Warehouse

@Entitypublic class Warehouse {

@Id public Long id;

public String name;

public String street; #A public String number; #A public String postalCode; #A public String city; #A public String country; #A

@OneToMany public List<StockItem> stock = new ArrayList<StockItem>();}

#A: Together, these properties form an address.While this would solve our problem, it also adds a lot of properties to the

class that are actually make up a single property of the warehouse: itsWarehouse

address. Therefore, it’s nicer to give the address its own class. Create the class as in listing 5.12:Address

Listing 5.12 Address.java

public class Address {

public Warehouse warehouse;

public String street; public String number; public String postalCode; public String city; public String country;

}

5.4.3 Giving our warehouse and address

80

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 84: Play for Java v2 Meaph

And then add an property to the class as in listingaddress Warehouse

5.13:

Listing 5.13 Warehouse.java

@Entitypublic class Warehouse {

@Id public Long id;

public String name;

public Address address;

@OneToMany public List<StockItem> stock = new ArrayList<StockItem>(); }

The address is neatly encapsulated in its own class

Figure 5.13 shows these classes in a diagram:

Figure 5.13 The Warehouse and Address classes in the data model.

Now to map this new relationship. The classes and Warehouse Address

have a relationship: a warehouse has exactly one address, and anone-to-one

81

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 85: Play for Java v2 Meaph

address belongs to exactly one warehouse. When looking at the database, aone-to-one relationship is indistinguishable from a one-to-many relationship; it ismapped by a foreign key column on one table, pointing to the primary key columnon another table, as illustrated in figure 5.14.

Figure 5.14 A One-to-Many database relationship.

But there’s a decision to be made while mapping a one-to-one relationship – weneed to pick the of the relationship. When we mapped theowning sidemany-to-one relationship, it was clear that the table on the "many" side had topoint to the primary key on the "one" side. It’s impossible to do it the other wayaround, since a database field may not contain multiple values. In the case of amany-to-one relationship, we call the "many" side the side of theowningrelationship; it’s the side where the relationship is stored.

In the case of a one-to-one relationship, it’s unclear what the owning sideshould be – both sides are capable of storing the relationship. Therefore, haveweindicate what side gets to be the owning side. When the relationship isunidirectional (say, on the warehouse only), it is sufficient to mark the field in

82

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 86: Play for Java v2 Meaph

question with the annotation. However, when the relationship goes@OneToOne

both ways, the fields on both side should be mapped with . To@OneToOne

indicate which side is the owning side, add the mappedBy parameter to point at theowning field. So, after we map our classes, they look like this:

Listing 5.14 Warehouse.java

@Entitypublic class Warehouse {

@Id public Long id;

public String name;

@OneToMany public List<StockItem> stock = new ArrayList<StockItem>();

@OneToOne public Address address;

}

Listing 5.15 Address.java

@Entitypublic class Address {

@Id public Long id;

@OneToOne(mappedBy="address") public Warehouse warehouse;

public String street; public String number; public String postalCode; public String city; public String country;}

In this case, we’ve picked the class as the owning side of theWarehouse

relationship. In the database, the relation between and isWarehouse Address

stored like shown in figure 5.15:

83

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 87: Play for Java v2 Meaph

Figure 5.15 A one-to-one database relationship.

Go ahead and create and persist a few warehouses with addresses, and checkthe database to see if everything goes as planned. Everything works the same aswith the one-to-many relationships.

TIP Always set both sides of a relationshipTo make sure a relationship between two entities is persisted, it’salways sufficient to set the field on the owning side of therelationship, and persist the owning entity. However, is therelationship is bi-directional, the other entity in the relationship isnow —it might still be pointing at the entity itinconsistentpreviously had a relationship to, or it might not be aware of it’s newrelationship. Therefore it’s wise to always set both sides of therelationship.

Now, there’s one more relationship we have to map: that between Warehouse

and .Employee

Let's look at our and classes. Figure 5.16 shows whereWarehouse Employee

they fit in the datamodel.

5.4.4 Mapping the Warehouse-Employee relationship

84

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 88: Play for Java v2 Meaph

Figure 5.16 The Warehouse and Employee classes in the data model.

In our situation, a single employee has access to many warehouses. This alsomeans that any warehouse has many employees with access. In our Java classhierarchy, this is represented by two s: a on List List<Warehouse>

, and a on . You can see this inEmployee List<Employee> Warehouse

listings 5.16 and 5.17

Listing 5.16 Employee

@Entitypublic class Employee {

@Id public Long id;

public String firstName; public String lastName;

public List<Warehouse> warehouses;}

Listing 5.17 Warehouse.java

@Entitypublic class Warehouse {

@Id

85

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 89: Play for Java v2 Meaph

public Long id;

public String name;

@OneToMany public List<StockItem> stock = new ArrayList<StockItem>();

@OneToOne public Address address;

public List<Employee> employees;}

Since both sides of the relationship can contain many instances of the otherside, this type of relationship is called a relationship. There’s amany-to-manyproblem when we want to map this relationship to the database: since there’s noway to store multiple values in a single database column, and both sides aremany-valued, there is no place to store foreign key to store the relationship.

The answer is adding an extra table to store all the relationships between ourtwo entities. This looks like figure 5.17:

Figure 5.17 A many-to-many database relationship.

Time to map our Java classes. The annotation to map many-to-manyrelationships is, of course, . Since we’re mapping a bidirectional@ManyToMany

relationship, we also need to designate one side the owning side, and tell the otherside which property is the owning property, using the mappedBy attribute likebefore.

@Entitypublic class Warehouse {

...

@ManyToMany public List<Employee> employees;

...}

86

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 90: Play for Java v2 Meaph

@Entitypublic class Employee {

...

@ManyToMany(mappedBy="employee") public List<Warehouse> warehouses;

...

}

Now, it’s important to note that any changes in this relationship are savedonlywhen the side is saved – , in this case.owning Warehouse

Now that we have our entire data model mapped to the database, see how toretrieve objects from the database. This is called the database.querying

As Java developers, we don’t really to write SQL queries to retrieve our datawantfrom the database. We know it’s what is used to communicate with the database,but we don’t want to deal with messy, untyped, string concatenation. We’d ratheruse some nice, object oriented, type-safe API to express what we want to do.Luckily, that’s just what Ebean provides.

We’ve already seen some of this kind of functionality when were saving objectsto the database—whenever we call , what happens behind the scenes issave()

that Ebean translates this method call into one or more SQL statements,INSERT

which is how you store a new record in a database table using SQL.Next, we want to do a similar thing for the database—that is, askingquerying

the database for data, based on some criteria. In the most simple case, query thedatabase for an object based on its ID. This is something you’d do when you knowexactly what object you want to access.

Now, we’re going be to be querying our database for some test data, so we’dbest have something interesting in it. If you’re in a DIY mood, go ahead and createand persist a few object hierarchies with some interesting test data. If you’refeeling lazy, like all good programmers, you could switch to the application for thischapter from our sample code archive. We’ve set it up so it preloads a bunch of testdata using the evolutions mechanism. Just run the application, and it will populatethe database on the first request.

Now, we should have a nice batch of test data loaded into our database. Let’sget to work.

5.5 Querying for objects

87

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 91: Play for Java v2 Meaph

Let’s retrieve a based on ID. We should have one in our database byProduct

now, so let’s look at the H2 console to find an ID for the product we saved last.Open H2 console, and click the table. It will populate the textarea onproducts

the right-hand side of a window with an SQL query that selects all rows from theproduct table. Click and look at the results. Note the ID for the last row, in ourrunexamples we’ll be assuming it’s "1".

We’ll be reusing the method as an entry point toApplication.index()

our application, so go ahead and empty it out; remove all lines but the last one:

public static Result index() { return ok(index.render("Your new application is ready."));}

Okay, now to find our product. Finding an entity based on its ID is so commonthat Ebean has a dedicated static method for it: . AsEbean.find(clazz, id)

you can tell from the parameters, all we need to tell it is what the class of the objectwe want to find is ( ), and what the ID is (1). Of course we needProduct

something to tell if it worked, so we’ll add some log output, as shown in listing5.9:

public static Result index() { Product product = Ebean.find(Product.class, 1L); Logger.info(String.format("Product name: %s", product.name)); Logger.info(String.format("StockItems: %d", product.stockItems.size()));

return ok(index.render("Your new application is ready."));}

Save the file, and reload in your browser. Switch to yourhttp://localhost:9000/terminal, and you should have the output as in figure 5.10:

[info] play - database [default] connected at jdbc:h2:mem:play[info] play - Application started (Dev)[info] application - Product name: Stainless paperclips, 1000pcs[info] application - Number of StockItems: 3

Success! We retrieved our Product, and we also confirmed that our mapping works. But calling the class directly is something@OneToMany Ebean

we avoided earlier, by extending , so let’s see if there’s something similarModel

we can do here.

5.5.1 Retrieving by ID

88

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 92: Play for Java v2 Meaph

Now, remember in section 5.3.3 how we added the method to the save()

class itself, by extending the class? Wouldn’t it be nicer to haveProduct Model

that for as well? It would be pretty trivial to add a static method to the find()

class that delegates to the method, but Play alreadyProduct Ebean.find()

provides an even better option for you: the class, which providesModel.Finder

a complete querying API for any entity.You will need to instantiate it, so let’s add a method to the Product class to

obtain a instance for s. Add the following method to the Finder Product

class:Product

...public static Finder<Long, Product> find() { return new Finder<Long, Product>(Long.class, Product.class);}...

As you can see, the constructor for takes two parameters, both Finder Class

objects. The first parameters tells the finder what type the ID field for the entity is,and the second parameter is the actual type of the entity we want to query for.

Now, let’s use our new API to rewrite our previous example. Changefind()

the first line of our method as follows:Application.index()

public static Result index() { Product product = Product.find().byId(1L); Logger.info(String.format("Product name: %s", product.name)); Logger.info(String.format("Number of StockItems: %d", product.stockItems.size()));

return ok(index.render("Your new application is ready."));}

While this example isn’t actually shorter, it makes for a more descriptiveinterface. Compare the two:

Product.find().byId(1L);Ebean.find(Product.class, 1L);

Both lines are equivalent, the only difference is in the API. The cool thing is, get to decide which one you prefer. Although it is recommended that you agreeyou

on a convention if you work in a team, of course.Selecting objects by ID is pretty useful in some cases, but in most applications

you’ll soon want some more powerful ways to query the database. Let’s see what

5.5.2 Using the Finder API

89

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 93: Play for Java v2 Meaph

else Ebean and the Finder class have to offer.

Databases are very good at for data on any criteria you want. Assearchingmentioned before, SQL is the language used when searching for data in a RDBMS.A downside of SQL when used in a object oriented enviroment, however, is that itis very much based on a relational view of the world – it's just not very compatiblewith object oriented programming, which is the whole point of our OR-mappingexcercise.

JPA and Hibernate (and some other solutions) get around this issue by defininga different query language, which looks a lot like SQL but allows you to queryclasses objects rather than database tables and columns.

However, creating queries like that using Java would mean using strings toform these queries. If we want to compose a query dynamically, which is a veryOO thing to do, we'd need to concatenate strings, and things get messy andconfusing fast, which means our code will hard to read, or worse, buggy. Workingwith Strings is just not something you want to do; among other things, it's tedious,messy and error-prone, and the compiler can't help us at all. In other words, it's justnot very nice to do in an type-safe world.

An alternative to constructing database queries is a -based API. Acriteriacriteria bases API allows you to use object composition to construct a query objectthat will construct and execute an (SQL) query for you. This means you don't haveto deal with messy strings, but you get to construct objects to tell the database whatyou want instead. Let's see how that works.

NOTE We'll stop showing you two API's now.Up to now, we've been showing you how to use both the Ebean APIand Plays Finder class. From this point forward, we’ll stop showingyou both the Ebean and the Finder APIs, and use only the Finder.Everything you can do through the Finder class, you can dothrough Ebean directly, so if you prefer to do things that way, readthrough the Ebean documentation to learn how to do things usingthe Ebean API. It's not very different, and the concept is exactly thesame.

When querying the database, you specify the following :clauses

data you wantWhatOne or more that data must satisfycriteria

5.5.3 Creating more complex queries

90

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 94: Play for Java v2 Meaph

The of the dataorder data you want (i.e. pagination)How much

Not all these parts of are required, however. If you omit any of these clauses,defaults are used instead. Here’s an example query, in plain English, that we couldask the database:

Give me all …sStockItem

… that have a …quantity of 300 or more… with …higher quantities first… but items is enough.ten

Using the Ebean, a query is constructed exactly like this—clause by clause.Let’s build up this example query. We’ll be using the Application.index()

method again. But first, add the following to the toString() StockItem

class, so stock items are a little easier to identify when we print objects later:

public class StockItem { ... public String toString() { return String.format("StockItem %d - %dx product %s", id, quantity, product == null ? null : product.id); }}

Next, we’ll use to run our code again. Only thisApplication.index()

time, instead of logging our objects, we’ll pass them to the browser directly, so wecan see the results in the browser. Start off with the following query:

public static Result index() {

List<StockItem> items = StockItem.find() .findList();

return ok(items);}

Here, we’re executing a query and rendereing the results as text. In this query,we’ve only told the database we want to find: StockItems. We did that whenwhatinstantiated the object, by passing in the class. Listing 5.18Finder StockItem

shows a reminder:

Listing 5.18 The method on find StockItem

...

The query isexecuted here

91

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 95: Play for Java v2 Meaph

public static Finder<Long, Product> find() { return new Finder<Long, Product>(Long.class, Product.class); //#A}...

#A We construct a that finds objectsFinder StockItem

So, when we run this code, we’ll get a complete list of all StockItems in thedatabase. Go ahead an refresh in your browser. You’ll seehttp://localhost:9000/output similar to this:

StockItem 1 - 300x product 1StockItem 3 - 500x product 1

Let's see what the next clause in the English version of our query is:

Give me all …sStockItem

… …that have a or morequantity of 300 … with …higher quantities first… but items is enough.ten

So, we want to add to our query to narrow the list of results down to thecriteriaobjects we’re interested in. To do this, we’ll use the method on ourwhere()

Finder objects, followed by the criteria we want or results to match.In this case, we want to specify a "greater or equal" criteria, which we can do

with the method. The criteria needs to know two things: what field it appliesge()

to, and what it’s target value is. We want to apply it to the quantity field, and thetarget value is , so we pass those values in. Our method now looks like this:300

public static Result index() {

List<StockItem> items = StockItem.find() .where() .ge("quantity", 300) .findList();

return ok(items);}

Reload the page in the browser, and the list should now only contain stockitems with quantities of 300 or more:

StockItem 1 - 300x product 1

FILTERING OUR SELECTION

92

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 96: Play for Java v2 Meaph

StockItem 3 - 500x product 1

Of course there are a lot more criteria available, browse the documentation forthe Ebean class for a full list.Query

So, let’s see what’s next for our query:

Give me all …sStockItem

… that have a …quantity of 300 or more… …with higher quantities first… but items is enough.ten

The list is now more or less randomly ordered. Well, actually it’s sorted by ID,but since we didn’t specify an order, the database is free to return items in anyorder it wants. Never trust on the default sort behavior, it might change if youswitch database vendor (like when taking your app to production).

Let’s specify an order clause. This is done using the method, specifyingorderBy

the field we want to order on; quantity, in our case:

public static Result index() {

List<StockItem> items = StockItem.find() .where() .ge("quantity", 300) .orderBy("quantity") .findList();

return ok(items);}

Refresh the page, and our list should be ordered now:

StockItem 3 - 500x product 1 StockItem 1 - 300x product 1

There’s just one more thing to add to our query:

Give me all …sStockItem

… that have a …quantity of 300 or more… with …higher quantities first… but items is enough.ten

The list of results is a little big, so let’s get just the first ten items. We need toset the maximum number of results, using the method:setMaxRows()

93

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 97: Play for Java v2 Meaph

public static Result index() {

List<StockItem> items = StockItem.find() .where() .ge("quantity", 300) .orderBy("quantity") .setMaxRows(10) .findList();

return ok(items);}

Reload the page, and our list should be trimmed:

StockItem 3 - 500x product 1

When developing a new application, you should definitely consider using Ebean –it’s just a better match for Play. However, there are a few good reasons to use JPAinstead. For example, you might just be more familiar with it, or you have legacycode you want to include, or you just think it’s cooler. Play won’t stop you. In fact,Play is even nice enough to include supporting features for it. We won’t go into thedetails of using JPA with Play (you’re probably already familiar with it, if youdecide you want to use it). So, here’s how you can set up your app to use Play.

There’s two steps to enabling JPA support in Play 2: exposing the datasource toJNDI, and adding a JPA implementation to the dependencies list.

First, open up your application.conf file, and add database configuration asregular (see section TODO). However, also add the jndiName property to yourdatabase configuration, like so:

db.default.driver=org.h2.Driverdb.default.url="jdbc:h2:mem:play"Adb.default.jndiName=DefaultDS

Remember what JNDI name you gave this datasource, you’ll need it when youdefine the persistence unit. Also, if you’ve already enabled Ebean, be sure toremove or comment out all lines starting with to disable it again.ebean

Next, open up project/build.scala to add a JPA implementation library to thedependencies list. You’re free to pick any JPA implementation you want. Here’sthe example for Hibernate:

5.6 Using JPA instead of Ebean

5.6.1 Configuring Play

94

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 98: Play for Java v2 Meaph

val appDependencies = Seq( "org.hibernate" % "hibernate-entitymanager" % "3.6.9.Final")

Now, if you next start your application, JPA will be available. However, youstill need to configure JPA itself – it needs a persistence unit, as usual.

There are no special steps needed to configure JPA for a Play application. Likewith all JPA projects, JPA requires persistence unit, declared in persistence.xml. InPlay, you need to put this file in the conf/META-INF directory. Listing 5.19 showsan example persistence.xml file, to correspond to the H2 datasourceDefaultDS

we configured in the previous section:

Listing 5.19 persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">

<persistence-unit name="defaultPersistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <non-jta-data-source>DefaultDS</non-jta-data-source> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/> </properties> </persistence-unit></persistence>

Now your JPA application should be good to go. Everything will work just asany other JPA application. However, there are some support classes in Play thatwill make your life easier

Here’s a small list of features that will help you when using JPA in a Playapplication:

: You can obtain an entity manager at any point in yourObtaining an EntityManager

application by calling .play.db.jpa.JPA.em()

: Annotate any action method with Wrapping action methods in a transaction to automatically wrap everything you do in that action [email protected]

5.6.2 Adding Persistence.xml

5.6.3 Built-in JPA helpers

95

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 99: Play for Java v2 Meaph

a transaction.I'm sure there will be more JPA support by the time the book goes to print.TODO:

In this chapter, we've created a basic datamodel for our warehouse application, andwe've seen how we can use Ebean to persist our objects to a database. We'veintroduced the principle of ORM, and basic JPA mapping principles have beenexplained, along with the basic relationship types:

One-to-ManyMany-to-OneOne-to-OneMany-to-Many

There is a lot more to JPA mapping than these relationship types, such asmapping class inheritance or embeddable objects, but those subjects are beyond thescope of this book. The Ebean documentation has a pretty good introduction ofmost features, but read the Java EE tutorial from Oracle if you want to knoweverything about JPA mapping.

We've also seen how to use Ebean and Play's Finder API to retrieve objectsfrom the database, once stored. The most simple form of this is retrieving an objectby it's ID, but we've also seen how to create more complex query using Ebean'sQuery API.

Throughout this chapter, we've been using convenience classes and methodsprovided by Play, as well as learned some best practices when creating an objectmodel with Play.

Perhaps the most important piece of advice in this chapter is to put onbehavioryour model classes. Most other frameworks discourage this, creating DAO layersinstead. Play is different, and helps you create non-anemic object models bymaking it easy to do it "right". The most important examples of this are the Model

and classes, providing nice and clean API, just by extending orFinder

instantiating them.

5.7 Summary

96

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 100: Play for Java v2 Meaph

6This chapter covers:

In this chapter we will explain in details one of the key concept of the playframework MVC paradigm: The controller part. We will build the first part of thewarehouse web application and at the same time explain how interaction with aweb client works in Play. We will start with controllers and then explain what arethe action methods and how to return results to web clients. We will then see howto route requests to a controller action method. From there, we will explain whatare interceptors and see in details what scopes are available in Play. This is ratherimportant as you will in fact be able to interact with client requests and send anappropriate response to those requests.

Let see how we can react to a request from a client.

First a bit of explanation of why the controller exists, then we will see how to usethem in play.

Controllers – handling HTTP requests

How to use controllers

Using Action methods and Results

Using Routing to wire URLs to action methods

Composing actions with interceptors

Using the different scopes

6.1 Controllers

97

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 101: Play for Java v2 Meaph

Usually, business logic is managed by the model layer. It means if you want to adda new product to the catalog, you would have to write some SQL. But, it would notbe very practical, would it? This is where web applications come to the rescue.Using a web application, the warehouse manager can interact with the databasestock level. This is an easier and cheaper solution than teaching SQL or having anon-site SQL expert.

However, there is still a problem: the web browser cannot directly access thosedata because it does not speak SQL. The web browser speaks HTTP. Moreover themodel layer is usually fine grained, whereas the user usually wants to execute aseries of action in one go. For example, when you add a product, you want to makesure it is a valid product and that the product was not already created.

This is precisely the role played by the controller. The controller connectsHTTP requests to the server business logic. It acts as a glue between domain modelobjects and transport layer events. A controller exposes some applicationfunctionality at a given address or URI (unique resource identifier). In fact, itexposes the application business logics at a given addresses: It is our webapplication public API. Like the HTTP interface, controllers are procedural andrequest/response oriented.

Figure 6.1 illustrates the role of the controller in a typical web application.

Figure 6.1 Role of the controller

It is one of the central point in play as in any MVC framework. It is also theentry point for you as a developer. As soon as a client (i.e. web browser) issue arequest, Play will process this request and delegate the processing of the request toa controller. This is usually where your code enter in action. Figure 6.2 illustratesthe described lifecycle.

6.1.1 About Play controllers

98

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 102: Play for Java v2 Meaph

Figure 6.2 Controller life cycle

In Play a controller is an aggregation of . An action method isAction methods

a method that takes some parameters in input that always return a Result. An is always of the following form:action method

public static play.mvc.Result method_name(params...)

Notice that action methods are static. This is because they are singleton, whichfits the HTTP approach. Because HTTP does not have the concept of object but ismainly procedural, we should not try to map those object concept in our controller.You should really think that your action methods are the entry point from HTTP toyour application and therefore see it as a sort of the method of Javastatic main()program. The idea is to discourage putting too much business logic in thecontroller.

It encourages delegation of the real business logic to another layer, which can

be the model layer as we saw in the previous chapter . The use of static methods1

also make the routing part and the reverse routing easier. Play makes sure theaction methods are thread safe. You will see that it has little impact over the wayyou code.

Footnote 1 Remember that object models are not supposed to be anemic, rathey they are supposed to performmbusiness logic in Play.

For now, imagine that play queues the requests coming in the controller inorder to process them as fast as possible. Netty and Akka are used under the hoodto dispatch and process users’s requests as fast as possible in a thread safe way. Inthe advanced section, chapter xxx, you can learn more about static methods and thethreading model play uses.

6.1.2 Action methods

99

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 103: Play for Java v2 Meaph

By default, all the controllers in Play are located in the app/controllers/ directory ofyour web application. You can change these defaults, but they rather suit us at themoment. As you know, a default controller as been created at the same time wecreated our warehouse web application.

Let’s create a new controller. Open your favorite editor and create a file called in the directory, as shown in figure 6.3.Product.java app/controllers

Listing 6.1 Project directory overview

warehouse |- app |- controllers |- Product.java #1 |- models |- views |- conf |-public |-test |-db

#1 the controller java file we are going to createThe first action method of this controller is to display the product items in stock

for a given warehouse. In this example the ok method constructs a 200 OKresponse containing a text/plain response body.

public class Product extends Controller { #1

public static Result list(long warehouseId) { #2 List<StockItems> stockItems = ... #3 return ok(StringUtils.join(stockItems, "\n")); #4 }}

#1 All controllers extend the Controller class. #2 Controller methods are statics.#3 Retrieve the stock items based on the warehouseId from the database #4StringUtils is a handy class that joins the elements of the provided array into asingle String.

The following code simply list all the product is stock. We override theStockItem method to print the product name and the associated quantity.toString

public String toString() { return product.name + " - " + quantity;}

6.1.3 Creating our first controller

100

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 104: Play for Java v2 Meaph

Edit the file application’s , as show in figure x.x.conf/routes

Listing 6.2 Project directory overview

warehouse |- app |- controllers |- Product.java |- models |- views |- conf |- routes #1 |-public |-test |-db

#1 the route file we are going to editAdd the following line:

GET /:warehouseId/products controllers.Product.list(warehouseId:long)

Don’t worry if you do not understand, we will explain that line in the nextsection. It basically links a given URL to an action method.

Now, if you point your browser to http://localhost:9000/1/items

you will see the following:

Stainless steel paperclips - 120Plastic paperclips - 190Red color paperclips - 200

As you can see, our items have been retrieved from the database. We now haveour first controller in place with our first action method. Let’s see action methodsand results in more details.

As figure 6.4 illustrates, a controller usually contains several action methodsmaking the controller useful for more than one use case.

Listing 6.3 Action methods in a controller

public class Product extends Controller {

public static Result list() { #A ... #A } #A

public static Result details() { #B

6.2 Action methods and Results

101

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 105: Play for Java v2 Meaph

... #B } #B

public static Result index() { #C ... #C } #C

}

#A Action method #B Action method #C Action methodAn action method is basically a Java method that processes the request

parameters, and produces a result to be sent to the client. An action is where theresponse is processed. Each action method returns a result. An action returns a

value, representing the HTTP response.play.mvc.Result

The following piece of code is an action method:

public static Result list(long warehouseId) { ... return ok(StringUtils.join(stockItems, "\n"));}

In the above example, the action method constructs a 200 OK responsecontaining a response body with product names and associated quantity.text/plain

Let see in details what our action method returns: a Result object. A result is aresponse to a client request. In our case, it is usually an HTTP response. It can bean ok with some text to the client, an error, something not found, etc… It can alsobe a redirect to another controller method.

For example, if a user enter an incorrect warehouse id, we should return:

return badRequest("Incorrect warehouse id: " + warehouseId)

This code returns an HTTP error code 400 with the following text Incorrect

as content.warehouse id: x

A better way would be to answer that we did not find the warehouse:

return notFound("No warehouse with id " + warehouseId);

This code returns an HTTP error code 404 with the following text No

as content.warehouse with id: x

6.2.1 Results

102

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 106: Play for Java v2 Meaph

Another handy object is the Redirect result object. As his name indicates,Result

it redirects the Action object to another action method. For example, using theRedirect result, we can redirect the user from the index method to the product listmethod, allowing our users to see a list of product on the main page.

public static Result index() { return redirect(routes.Product.list(1)); #1}

#1 Redirect to the product list action method.The routes object is a class that was generated by Play 2 based on your routes

file. The file contains only static members that allow you to access your controllermethods. For now, remember that the Redirect result redirects from one actionmethod to another action method. We will go into more details in the next section.

SIDEBAR TIP:There is also an handy Result object called Todo. As you guessed, thisResult indicates that the action method implementation needs to bedone. This is rather useful as you develop and you do not have youraction method implementation finished, but you need to return a result.For example, if we have the following action method but ourimplementation is not ready yet, we can return a TODO result:

public static Result items() { return TODO; #1}

#1 The client receives an not implemented HTTP code.

We are now able to respond to clients and send back text. It is all very nice, but wewould like to return something more elaborate than text. Ideally we want to returnsome HTML, after all we are developing a web application, right?

We want to change the content type we are returning to HTML. All those actionmethods let you pass a object as parameter. And it turns out thatContent

templates in Play are also .Content

We will build our first template and pass that as a parameter Result. Open youreditor, and edit a file called in the app/views directory (figureproduct.scala.html6.5).

6.2.2 Redirect result

6.2.3 Using Results

103

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 107: Play for Java v2 Meaph

Listing 6.4 Project directory overview

warehouse |- app |- controllers |- Product.java |- views |- product.scala.html #1 |- conf |- routes |-public |-test |-db

#1 the view file we are going to createAdd the lines listed in figure 6.6 in the product.scala.html file.

Listing 6.5 Displaying our stockitems

@(stockItems: List[model.StockItem]) #1

<!DOCTYPE html><html> <body> <!-- Lots of pictures somewhere here --> <img src="..."/> <ul> @for(stockItem <- stockItems) { #2 <li>@stockItem.product.name (@stockItem.quantity)</li> #3 } </ul> </body></html>

#1 Indicates that we are passing a List of stockItems as parameter to ourtemplate. #2 Iterates though the stockItem list #3 Access the stockItem object

We have our first template. For now, do not worry if you do not understandeverything. The template basically prints the list of products with thecorresponding quantity. What you need to know is that play automaticallycompiles the template when it sees it. This means that our template file is compiledinto a class that is accessible to the controller. By convention, it is compiled into

. In our case, it is compiled into aviews.html.{name of the template}

views.html.product` class. The generated classes define a render method. Alltemplates are type safe in play, that is why we have to pass the stockItems asparameter. It will be explained in detail in chapter xxx.

Now, what matters to us at the moment, is to understand how from our

104

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 108: Play for Java v2 Meaph

controller we send back some HTML. The HTML in question is this template. Inorder to solve this problem, you need to know that the template code happens toalso be a object. Each Content object have a render method. With that inContent

mind, the answer on how to render HTML from our controller comes immediately:

public static Result list(long warehouseId) { ... return ok(products.render(stockItems)); #1}

#1 This is in fact a call to the generated template based on theproduct.scala.html file.

Now, point your browser to s andhttp://localhost:9000/1/product

you will see the same screen as figure 6.7:

Figure 6.3 Our stock items

Here is what happens: the template is loaded by the framework and generatessome HTML. This is called rendering the template. The generated HTML isincluded in the result object and sent back to the client (figure 6.8).

105

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 109: Play for Java v2 Meaph

Figure 6.4 Detailed view of the controller life cycle

We have displayed some HTML without much effort: we only changed the object in our action method. That’s great! Let’s do something extra (IResult

hope you are thinking the same as I do). Let’s serve the client with the type ofresult he is asking for. If the web client asks for text, we return some text, if heasks for HTML we are returning some HTML. This is easily done with Play:

if (request().accept("text/plain")) { #1 return ok(StringUtils.join(stockItems, "\n"));}return ok(products.render(stockItems));

#1 the request() method access the current request.We are now able to serve content according to the client wishes. We added our

object to the diagram to explain the complete request / responseContent

lifecycle in play, as shown in figure 6.9.

106

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 110: Play for Java v2 Meaph

Figure 6.5 Adding Result to the controller life cycle

We are now able to respond to a request with some content. We now need toexpose our action methods to our client.

We know how to render some content and how to execute some business logic. Buthow do we relate the controller method to be executed to the URL the clientinvokes? This section will answer exactly that specific question.

Remember, our client only speaks HTTP. However, the code that we are writing isin Java. We therefore need to translate the HTTP language to Java language. Yes,you have guessed it, the router is the component in charge of translating eachincoming HTTP request to an action method call. It exposes the controller’s actionmethods to the client. An HTTP request can been seen as an event by the playframework, where the router role is to coordinate the reaction to such an event(figure 6.10).

6.3 Using Routing to wire URLs to action methods

6.3.1 Translating HTTP to Java code

107

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 111: Play for Java v2 Meaph

Figure 6.6 Role of the Router

Two major pieces of information are contained in the request:

the request path (such as /clients/1542, /photos/list), including the querystring (such as id=2).

the HTTP method (GET, POST, …).

For example, when you enter the following 'http://localhost/` address in yourbrowser, let’s say to view the home page, it issues a request to the localhost

server. The request is decomposed as in figure 6.11:

Figure 6.7 Request

Another example, to display the first page of a product listing, an URL wouldbe, http://localhost/products?page=1. It would decomposed

as shown on figure 6.12.

Figure 6.8 Request with query string

The HTTP method can be any of the valid methods supported by HTTP (GET,POST, PUT, DELETE, HEAD). The request path identity the resource we aretrying to serve. Query string are optional and are used to provide parameters thatare dynamic. Query string are specified after the sign and always of the form?name=value. We assume you know all about what an URL is and what HTTPmethods are. If not, please read about it in chapter xxx.

Lets get back to our application. We would like to provide the followingfunctionality and therefore we should be able to respond to the following requests.

Method Request path Description

108

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 112: Play for Java v2 Meaph

GET / Home pageGET /products Product listGET /products?page=2 The product list’s second pageGET /products?filter=zinc Products that match ‘zinc’GET /product/5010255079763 The product with the given codeGET /product/5010255079763/edit Edit page for the given productPUT /product/5010255079763 Update the given product details

As you guessed it, we need to translate each request to a controller actionmethod. We are translating each HTTP request into Java code. The translation initself is what we call a route definition. A route definition is simply a path to Javacode. Route definitions are contained inside a routes file. The routes file exposesthe above application functionality.

Routes are defined in the conf/routes file as show in the

figure 6.13.

Listing 6.6 Project directory structure

warehouse |- app |- controllers |- Product.java |- models |- views |- product.scala.html |- conf |- routes #1 |-public |-test |-db

#1 the route file that contains the routes to your controller’s action methodsThe routes file is compiled into an object. The object is accessible in our

controllers and is called routes. This means that you’ll see route errors if a routedefinition is not valid or if a requested url does not exist in our application, asshown on figure 6.14.

109

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 113: Play for Java v2 Meaph

Figure 6.9 Play error screen

This is rather handy as you know immediately that something is wrong in yourapplication. This was not the case in Play 1, but as we already explained, Play 2concentrates on type safety to make your application more robust.

public class Product extends controller {

public static Result index() { return redirect(routes.Application.products()); #1 }

public static Result products() { ...

Let’s get back to our routes. What are they? As explained previously, the routesfile is where the translation between HTTP request and your code is done. Let seein more detail the route file syntax. This file lists all of the routes needed by theapplication. Each route consists of an HTTP method and URI pattern associatedwith a call to an action method. This is what we call a route definition.

Let’s see what a route definition looks like for home page:

GET / controllers.Products.home() #1

THE ROUTE FILE IS TYPE SAFE

6.3.2 The route files explained

110

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 114: Play for Java v2 Meaph

#1 We assume that we have a Products controller with a home action method.This means that when a client issue an HTTP request the action methodGET /

located in the Products class should be called. The Products class is our code, thisis our entry point. In the route file, the route above route definition is composed ofthe following parts (figure 6.15):

the first part is the HTTP methodthe second part is the request path.a third optional part is the query string.the last part is the call definition.

Figure 6.10 Route definition

The same illustration - figure 6.16 - but with the optional query string.

Figure 6.11 Route definition with query string

Let’s now see, a route definition a bit more complex. We want to have a routedefinition, that display a product details based on the product id. We could have thefollowing entries in our route files:

GET /product/1 controllers.Products.details(1)GET /product/2 controllers.Products.details(2)GET /product/3 controllers.Products.details(3)....

But that would not scale very much. You understand it now, we need to have away to have a dynamic part in our route definition.

GET /product/:id controllers.Product.details(id: Long)

Note that in the action call, the parameter type comes after the parameter name.Please note that for parameters of type String, typing the parameter is optional.

111

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 115: Play for Java v2 Meaph

Now, every time we request /product/1 in our browser, the details method on theProduct controller is called with as parameter. Play makes sure the get1transformed into a Long. Play is also able to convert to other types such as arrays,custom type, etc…

If Play cannot convert to the require type, it probably means that the expectedtype is not the good one and that your are doing something you should not. Youwill also see the following default screen (figure 6.17):

Figure 6.12 Bad request error screen

This is a really nice feature that allows us to concentrate on our problem athand. If you were using Servlet or any other framework, you would probably haveto write something along the lines:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { final String id = request.getStringParameter("id"); final Long idCode = Long.parseLong(id); // Process request... } catch (NumberFormatException e) { final int status = HttpServletResponse.SC_BAD_REQUEST; response.sendError(status, e.getMessage()); }}

Type conversion is handled automatically by Play, so you can concentrate on theproblem at hand, instead of converting forth and back Strings to other types. Theautomatic conversion is called binding. It is HTTP binding to Java type. We will inchapter xxx explain that Play can bind other types. This is actually part of thetranslation process from HTTP to your Java code.

If you have experience with regular expression, you will notice the defaultmatching strategy for a dynamic part is defined by the regular expression [^/]+,meaning that any dynamic part defined as :id will match exactly one Request pathpart.

6.3.3 A word about simple data binding

112

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 116: Play for Java v2 Meaph

However, sometime, you might want more flexibility: if you want a dynamicpart to capture more than one request path segment, separated by forward slashes,you can define a dynamic part using the regularid syntax, which uses the .expression:

For example, let says that we want to get the path to our product image, theroute definition is as follow:

GET /product/image/*imagePath controllers.Product.downloadImage(imagePath: String)

If we issue a request like GET /products/image/29929/cocacola.jpg theimagePath value will be 29929/cocacola.jpg.

If you know what regular expression are, you can also define your own regularexpression for the dynamic parts, using the syntax:$id<regex>

GET /product/$id<[0-9]+> controllers.Product.details(id: Long)

This route definition will only apply if the id is a number, which is quite handyin our case, because we know that our product id are numbers. Play will return a

error code in case we enter alpha numeric characters as id.not found

As you know, you can also pass parameters in your URL. For example, . How can I find the parameter in thehttp://google.com?query=playframework

action method? Do I need to declare them in my route file as well? The shortanswer is no, you don’t need to define them in your route file. And you use them inyour action method by specifying them on the method signature:

public static Result products(String query) { #1 ...

#1 query might be a query string parameter i.e. http://localhost/products?query=playframework

If the action method defines some parameters, all these parameter values will. They will either be extracted from the requestbe searched for in the request path

path as we saw before or they can be extracted from the query string.Let’s see a more detailed example. Let’s say we want to display a list of

products. However, this is a really large list, so we want to paginate this list. Toaccess the first 20 items, we will request the first page, the next 20, we will requestthe second page, etc. The following route definitions can be seen as equivalentfunctionally:

113

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 117: Play for Java v2 Meaph

GET products/:page controllers.Product.list(page: Int)GET /products/ controllers.Product.list(page: Int)

What is the difference between the two route definitions? The first routedefinition has the page parameter part of the actual request path. The client requestthe following url to access the second product list page: .http://localhost/products/2The second route definition does not require the page parameter to be part of therequest url. Instead it is a parameter that the user needs to provide. This is done byrequesting the following url: .http://localhost/products?page=2

It is interesting to notice that isn’t a identifier for ahttp://localhost/products/2resource. By resource, we mean the product list. The product list for the secondpage is likely to change over time. Therefore the second definition is to bepreferred. For more information about RESTful concepts, please refer to ….

Also notice that play complains if we do not specify the page parameter in therequest url, as show on figure 6.18 :

Figure 6.13 Bad request error screen for missing parameter

This is why we can (and should) also use a default value if none is specified. Forexample, for our list of products with pagination, the following syntax will requestthe first page to be displayed if no first page is specified.

GET /products controllers.Product.list(page: Int ?= 1)

Now, lets say that we want the home page to display the first page of our productlisting. We can do that using a fixed value as parameter:

GET / controllers.Product.list(page: Int = 1)

ROUTE WITH DEFAULT VALUE

FIXED VALUE AS PARAMETER

114

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 118: Play for Java v2 Meaph

Because many routes can match the same request, if there is a conflict, the firstroute (in declaration order) is used. For example, if we were to have the followingroute definitions:

GET /product/$id<[0-9]+> controllers.Product.details(id: Long)GET /product/:id controllers.Product.view(id: Long)

The following request would match thehttp://localhost/product/1

first route definition.

We now know enough about the route definitions. Let’s get back to our applicationand edit the routes file with all the right definitions:

# Home pageGET / controller.Product.index()# This would have worked as well# GET / controllers.Product.list(page: Int = 1)# Product pagesGET /products controllers.Product.list(page: Int ?= 1)PUT /product/:ean controllers.Product.save(ean: Long)GET /product/:ean/edit controllers.Product.edit(ean: Long)GET /product/:ean controllers.Product.details(ean: Long)

Now, for we need to add the same relevant code to our controller.We are now ready to complete our implementation. We need the relevant

controller code, as shown in figure 6.19:

Listing 6.7 Our product controller

public class Product extends controller {

public static Result index() { return Redirect(routes.Product.list(1)); #1 }

public static Result list(String page) { return TODO; #2 }

public static Result details(String ean) { return TODO; #2 }

public static Result edit(String ean) { return TODO; #2 }

CONFLICTING ROUTES

6.3.4 Conflicting routes

115

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 119: Play for Java v2 Meaph

public static Result save(String ean) { return TODO; #2 }

#1 Redirect to you product list action method. #2 Handy play Result thatindicates we need to implement the method.

The index method is quite interesting. It basically redirects the user to the listmethod. You surely have noticed the call to the routes object. This object wasgenerated by Play 2 based on your routes file and your controller. The objectcontains only static methods that return an Action. It exposes our action methods tothe controller, but also anywhere else we might need it (in our views for example),as the routes object is a singleton. Our action methods are added as methods to ourroutes object at compilation time, when play generates the routes file.

It provides what we call .reverse routingReverse routing is quite important as it allows us to get an HTTP request for a

given action method. It is basically translating from Java code to HTTP request,this effectively performing the reverse operation a router usually does. Forexample, you want to be able to point your client to the edit method. And,remember, your client only speaks HTTP. You need to return an HTTP call: anHTTP Method and an URL. It is as simple as asking the Routes object. The Routesobject returns a play.mvc.Call object. The play.mvc.Call defines an HTTP call, andprovides both the HTTP method and the URL. It also makes sure the method call iscorrectly translated, especially when parameters are part of the action method. Forexample the following call:

routes.Product.list(4)

is translated to

GET /products/3

You now know everything about how to translate HTTP request to actionmethod and vice-versa with the reverse routing. You should now have a completefigure on how Play operates when a request is received from the client andexecuted as Java code. It is now time to see in more details how we can simplifysome tedious operations in the controller.

6.3.5 Reverse routing

116

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 120: Play for Java v2 Meaph

Let’s get back to our warehouse application. From time to time, an exceptionoccurs. However, we cannot spot it. It would be nice if we could just tell Play: ifthere is an exception for this action methods or inside this controller, please sendme an email with the error.

Action methods can easily be composed. It means that you can add extrabehavior to action methods. And it is what we want to achieve: we want to catchany exceptions occurring in our action methods and send an email about then. Let’ssee how we could meet our requirement:

Play provides a annotation to compose an action. The annotation is@With @With

used before an action method declaration. It can also be used on the class level: onthe controller itself. By declaring the annotation on our action method, it@With

tells play that certain action must be performed around each action methodexecution, mainly before and after. The takes one parameter: the Action we@With

want our code to be composed with. We will build a class shortly.CatchAction

For example, the following code tells play it must execute the action methodusing the CatchAction action:

@With(CatchAction.class) #1 public static Result list(long warehouseId) { .... }

If we were to declare it at the class the level, the CatchAction would be used forall the controller’s action methods:

@With(CatchAction.class) #1 public class Product extends Controller { .... }

But what is exactly this CatchAction class? This is actually what we have tobuild. The annotation takes an Action object as parameter. An action object@With

must implement the

public Result call(Http.Context ctx)

method. The call method is called before the action method execution. Fromthere, the call method actually calls the action method using the delegate object.The delegate object is a reference to the action method that is marked with the

annotation.@With

6.4 Interceptors

6.4.1 The @With annotation

117

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 121: Play for Java v2 Meaph

Let’s just implement that by extending the abstractPlay.SimpleAction

class that Play provides. The class provide everything wePlay.SimpleAction

need to get started. Let’s define our CatchAction, that will catch any exceptionsand mail them.

public static class CatchAction extends Action.Simple { #1public Result call(Http.Context ctx) { #2 try { return delegate.call(ctx); #3 } catch(Throwable e) { ExceptionMailer.send(e); #4 } }

#1 We extend the Action.Simple class that implements the Action interface. #2This is the main method we need to implement. Note that we can access thecontext. #3 Call our action method: our code is executed #4 Any exception is catchand we delegate sending an email to our ExceptionMailer object

The actual call to the action method is done via the delegate object. Note that wehave access to the Play context object. The context object hold our session,request, response and flash objects. We will see that in more details in the nextsection. In case an exception is triggered, we catch it, and our ExceptionMailerobject send an email with the exception stack trace. The ExceptionMailer objectcode is not relevant at this moment, as the goal is to show you how interceptorswork.

We now have the Action that can send email in case of exception occurring inour action methods. Let’s use it in our controller.

As mentioned early, the allows us to compose Action. By specifying@With

the annotation on our action method call, we tell Play to wrap the action@With

method inside the SpyAction call method.

@With(CatchAction.class) #1public class Product extends Controller { .... }

#1 the @With annotation is specified at the class level. It will be noticed byPlay for all the MyController’s action methods

We just told Play that when a call is done to any controller action methods, hemust in fact execute the CatchAction call method that:

6.4.2 The delegate object

118

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 122: Play for Java v2 Meaph

call the original action method

catch any potential exception and send an email

An action method wrap you current controller code. You controller code isexecuted by the delegate.call method.

Note that we can of course mix multiple Actions. For example, if we were to havea LogAction that would log any access to our controllers:

@With(CatchAction.class, LogAction.class)

If you are familiar with annotations, you can also define your own. This is morereadable and allows re-use across multiple web applications. Our CatchActionwould then become:

@With(CatchAction.class) #1@Target({ElementType.TYPE, ElementType.METHOD}) #2@Retention(RetentionPolicy.RUNTIME) #3public @interface Catch { #4

}

#1 Indicates that we want this annotation to use the CatchAction class wedefined previously. #2 The annotation we are defining applies to methods andclasses. #3 The annotation we are defining is to be used at the runtime #4 Ourannotation definition

Using our freshly defined annotation, we can now annotate our controller asfollow:

@Catch #1public class Product extends Controller { .... }

#1 Our newly defined annotationNote using our own annotation we can also pass extra configuration

information. Using the previous example, we can for example specify if we onlywant to log the exceptions or if we want to mail the exceptions. Let’s redefine ourcatch annotation:

@With(CatchAction.class) #1@Target({ElementType.TYPE, ElementType.METHOD}) #2@Retention(RetentionPolicy.RUNTIME) #3

6.4.3 Action composition

119

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 123: Play for Java v2 Meaph

public @interface Catch { #4 boolean value() default true; #5}

#1 Indicates that we want this annotation to use the CatchAction class wedefined previously. #2 The annotation we are defining applies to methods andclasses. #3 The annotation we are defining is to be used at the runtime #4 Ourannotation definition #5 Indicates if we want to mail the exception. By default, wewant to mail them.

The annotation value can be accessed via the configuration object in our action.Figure 6.20 show s the code to catch the exceptions.

Listing 6.8 The CatchAction listing

public static class CatchAction extends Action.Simple { #1 public Result call(Http.Context ctx) { #2 try { return delegate.call(ctx); #3 } catch(Throwable e) { if (configuration.value) #4 ExceptionMailer.send(e); #5 else e.printStackTrace(); #6 } }}

#1 Extend the Action.Simple class that implements the Action interface. #2Main method we need to implement. #3 Call our action method #4 The annotationvalue: the configuration object is our annotation object. #5 Exception is catchedand email is sent #6 No email then log the error

We are now able to be notified of any exceptions occurring in our code. This isa trivial example, but think about transactions, security and I am sure you willcome up with some more interesting examples. It is now time to see in more detailswhat are our options if we were to save user’s data.

120

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 124: Play for Java v2 Meaph

We saw that, using the controllers and the routes, we are able to retrieve data fromthe clients and push back data to those clients. We did not really talk about thelifetime and accessibility of those data. We assumed the data were transmitted eachtime a communication was made between the server and the client. Well, that isreally what is happening. However, as a developer, you don’t really want tomanage all the data flow. You want to store data for a certain lifetime. You storethose data in a certain scope. See it has a sort of Map storage where your data arestored for a certain lifetime.

Java EE traditionally defines three scopes:

Application scopeSession scopeRequest scopePage scope

The application scope has a application lifetime: you store data that will stay aslong as your application is running.

The session scope has a session lifetime: you store data that will stay as long asyour browser is open. This is traditionally the JSESSIONID parameter you see thefirst time in your URL. The JSESSIONID is also stored in a cookie, so it is alwaysavailable on consecutive requests by the server. This JSESSIONID is just an IDthat points to some server side storage space. The session scope is usually used tostore information about your shopping basket or the fact that you are logged in.

The request scope defines data with a lifetime of request: the client makes anHTTP request. With the request comes some data. Those data are stored in therequest scope and can only be accessed while that particular request is processed.

The page scope defines data that are accessible in the view only, meaning thatthey can be accessed during the rendering phase. For example, you might want tostore the current breadcrumb of your application in that scope, to display thecurrent application path.

The different scopes can be conceptually viewed as shown on figure 6.19.

6.5 About scopes

6.5.1 A bit of history about the scopes

121

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 125: Play for Java v2 Meaph

Figure 6.14 In JEE, application scope isthe longuest lived and page is theshorted

SIDEBAR NOTEWhile some Java EE framework came up with a conversation scope,we do not think this is relevant for our explanation and would confusethe reader more than anything else.

Now, in a traditional Java EE environment, all the storage happens server side.This means that each client got a unique id and the server uses that unique id toretrieve the client storage space server side.

While it has the advantage of potentially using less bandwidth it can beproblematic when scaling up (adding more server), since you need to synchronizeall the client storage space between the different servers. Another disadvantage isthat it makes the servers compute more operation while the client stays idle. It usedto be an advantage, but nowadays, web clients are powerful beast. An iPhone ismore powerful cpu wise that any computer older than 5 years. Moreover, webstandards evolved and allow clients to accomplished wonders, local storage andweb worker being examples of those wonders.

Now, you guess it, Play is a bit different than the Java EE framework. It isinteresting to note that it is actually not so different than other language webframeworks, such as Django, Ruby on Rails, Symphony.

Play defines four scopes:

Session scope

6.5.2 The Play scopes

122

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 126: Play for Java v2 Meaph

Request scopeFlash scopeResponse scope

Before we start explaining those scope, there is a fundamental differencebetween Play and the more traditional Java EE framework (read servlet basedframework). Because of that fact,Play does not store any data server side.scaling up is really with Play. Just add a new server and a load balancer and youare done. No server side session replication needed and no risk of loosing data onthe server since there is no data. But, how does that work? What is Play’s secret?

Well, really there is no secret, Play is storing the data on the client side usingcookies. It also encourages developers to think differently, to architect theirapplication differently and to fully embrace client side technology. While a JavaEE developer would see the session as a giant cache where everything is allowed,Play forces the developers to think in term of web development. And that is a goodthing since we happen to use Play mainly to develop web application. So, no, youcannot store your complete object tree in your session. And no, you cannot saveyour last 10000 database results. In fact you can store up to 4KB (a cookie size)and you can only store String values. You might see that as a regression in time,but we will attempt to explain you that it is a progression. But, first let’s explainthe 4 play scopes.

The four different scopes can be conceptually viewed as shown on figure 6.20.

Figure 6.15 In Play, Requestscope is the shortest lived andSession is the longuest

123

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 127: Play for Java v2 Meaph

SIDEBAR What is a cookie?A cookie, also known as an HTTP cookie, web cookie, or browsercookie, is used for an origin website to send information to a user’sclient browser and for the client browser to return the state informationto the origin site. For example, the information can be used forauthentication, identification of a user session, user’s preferences,shopping cart contents, or anything else that can be accomplishedthrough storing text data on the user’s computer. A cookie can only beused to store text.

First of all, all accessible scopes in Play are stored in a Context object. The Contextobject is a final static class that contains the Request, the Response, the Sessionand the Flash objects. You can access it statically. From there you can access allthe play scopes:

Context ctx = Context.current(); #1Request request = ctx.request(); #2Response response = ctx.response(); #3Session session = ctx.session(); #4Flash flash = ctx.flash(); #5

#1 The Context object #2 The Request object #3 The Response object #4 TheFlash object #5 The Session object

The request, response, session and flash objects are also available by default inyour controllers, as they are part of the Controller object that any controller mustextend.

What about thread safety? Well that is really easy. Each Context object isassociated to the current thread using a ThreadLocal object. It insures that there is ano thread safety problem and that your context object is really your context objectand not the one from your neighbor: Each thread holds an implicit reference to itscopy of a thread-local variable. We are sure that our scope objects are our scopeobject and they are thread-safe.

The Request scope cannot be used to store objects. It is used to access the data ofthe current request. For example, you can access the current logged in usernamevia the Request scope.

6.5.3 The context object

THE CONTEXT OBJECT IS THREAD SAFE

6.5.4 The Request scope

124

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 128: Play for Java v2 Meaph

The Response scope cannot be used to store objects. It is used to set the responsecontent type and eventual extra cookies to store extra information.For example,you can set the response content type to xml with the following code:

Context.current().response.setContentType("application/xml");

SIDEBAR ChartsetFor text based HTTP response it is very important to handle the charsetcorrectly. Play handles that for you and uses utf-8 by default.The charset is used to both convert the text response to thecorresponding bytes to send over the network socket, and to modify theContent-Type header with the proper ;charset=xxx extension.The charset can also be specified when you are generating the Resultvalue, in that case the ok result value:

public static Result index() { response().setContentType("text/html; charset=iso-8859-1"); #1 return ok("<h1>Hello World!</h1>", "iso-8859-1"); #2}

#1 set the charset (encoding) on the reponse #2 tell that our result isusing the iso-8859-1 charset

Using the response object we can also store extra data with a new cookie on theclient. For example, if we were to save the preferred theme for our application,from our controller:

response().setCookie("theme","blue");

Then, on a next request, from our controller’s action method, we could check ifthe theme was set, using the cookie method:

public static Result index() { if ("blue".equals(cookies("theme").value())){ // Do something } ....}

You could also store more information by serializing your data into strings, butremember that you can only store up to 4Kb per cookie. Therefore, save only whatyou need, which is mainly entity IDs usually.

6.5.5 The Response scope

125

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 129: Play for Java v2 Meaph

Finally to discard a cookie previously set:

response().discardCookies("theme");

As you can see, the response object is rather straight forward.

Object stored in the session scope have an session lifetime: you store data that willstay as long as your browser is open. It's important to understand that Session arenot stored in the server but are added to each subsequent HTTP Request, using theCookie mechanism. So the data size is very limited (up to 4 KB) and you can onlystore String values.

To store a value in the session:

Context.current().session().put("x", "myvalue"); #1String value = Context.current().session().get("x"); #2System.out.println(value); #3

#1 Store the value in the session with key #2 Retrieve the value frommyvalue xthe session #3 Prints myvalue

From the controller you can also use the convenience methods provided by thecontroller:

session("x", "myvalue"); #1String value = session("x"); #2System.out.println(value); #3

#1 Store the value in the session with key #2 Retrieve the value frommyvalue xthe session #3 Prints myvalue

SIDEBAR Why can I store string only in my Session?You may argue that it is a regression, however we feel that it is the wayit should be. By disallowing storing complex object graph we are alsoremoving a lot of associated problems synchronizing the object statesand/or any side effects. By storing immutable objects such as string inour session no side effect can occur. For example, if we were to storean attached (marked as connected to the DB) entity in our session, theentity might really well be detached (no more connected to the DB) thenext time we access the object causing all sort of troubles. Or the entitymay have been modified by a third party since we last accessed it,causing unexpected behavior.

6.5.6 The Session scope

126

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 130: Play for Java v2 Meaph

Object stored in the flash scope have a lifetime of exactly 2 requests. It means thatdata in the flash scope will survice one redirect. This is really handy when youwant to retain data after a redirection. To understand better, let’s take a concreteexample:

The client issue the following request:

GET /

The server render an HTML page. On the page we have a form to input atelephone number with a submit button. When the user submit the form, a POSTrequest is made to the server to the following address:

POST /phonenumber/

Now, once the controller receives the request, it attempts to validate the phonenumber. In case the validation fails, the server render the same page with an errormessage. However, if you try to refresh your browser, you are up for a surprise:you browser is asking you if you want to resubmit the data. Why is that? This isbecause, as far as your client is concerned, it’s last execution point matches POST

. And indeed, the url that your browser shows is /phonenumber.http://localhost:9000/phonenumber

The figure 6.21 illustrates the problem we just described.

Figure 6.16 Submitting a invalid form without using the flash scope

A way to avoid bad surprise is to send a REDIRECT instruction to your client,

6.5.7 The Flash scope

127

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 131: Play for Java v2 Meaph

so it redirects to . But of course, in the meantime, because of the redirect,GET /you lost your error message. This is exactly for this use case the flash scope hasbeen invented. Storing the error messages in the flash scope allows you to stillhave access to your error messages after the redirect.

In Play, the error messages are in fact stored in the flash scope, in a specialcookie that is flushed after the second consecutive request.

This figure 6.22 illustrates the same problem but with using the flash scope as asolution.

Figure 6.17 Submitting an invalid form and using the flash scope

SIDEBAR NOTEThe Flash scope has been introduced in Java EE 6 and defines thesame lifetime as his play equivalent but lives server side. At the time ofwriting, most Java EE web framework do not have flash scope.

Of course, cookies are signed with a secret key so the client can’t modify thecookie data (or it will be invalidated). The Play session is not aimed to be used as acache. If you need to cache some data related to a specific session, you can use thePlay built-in cache mechanism and use store a unique id in the user session to keepthem related to a specific user.

The secret key used to sign the cookie is actually set in your file (figure 6.23).conf/application.conf

Listing 6.9 Project structure

warehouse |- app |- controllers

6.5.8 What about security?

128

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 132: Play for Java v2 Meaph

|- Product.java |- models |- views |- conf |- routes |- application.conf #1 |-public |-test |-db

If you edit the file, you will find the following line.application.conf

application.secret="FuqsIcSJlLppP8s?UpVYb5CvX1v55PVgHQ1Pk"

This is the key we are signing our cookies with. It is essential to keep it secret,so be sure you don’t divulgue your key. It brings us to another important point, ifyou are running multiple instances of your application, the secret key needs to beshared between the applications.

Let’s imaging the following scenario: 1 load balancer and the same applicationrunning on two different nodes: server1 and server2. Each client can either bedispatched to server1 or server2. If server1 and server2 do not share the same key,the clients need to always communicate with the same server, otherwise the servercan not decipher the cookies. If both server1 and server2 have the same key, theycan decipher the same cookies and the client does not need to make a differencebetween server1 and server2.

The figure 6.24 illustrates the data encryption / decryption flow.

129

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 133: Play for Java v2 Meaph

Figure 6.18 Secret key with a cluster of applications

SIDEBAR But what about my session time out?We can argue that session time out were introduced, not as a usefulfunctionality but more as a technical solution for the server side sessionstorage. Indeed, without this feature, user session could only grow onthe server resulting in memory depravation. However, developers areso used to session timeout that they actually see those as usefulfunctionality.In Play there is no technical timeout for the session. It expires when theuser close its web browser. If you need a functional timeout for aspecific application, just store a timestamp into the user session andcheck it along your application needs (max session duration, maxinactivity duration, etc.).

130

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811

Licensed to Dennis Vis <[email protected]>

Page 134: Play for Java v2 Meaph

We started this chapter by explaining what controllers are. We then looked into thespecifics of Play controllers and more particularly the controller’s action methods.We learned about routing our client requests to our action method code.

Let’s pull out some of the key practices to take away from the chapter:

Use flash scope. Flash scope is ideal for passing messages to the user (when a redirect isinvolved).Use action methods. This is the entry point for your business logics. Keep them short anddelegates all business logic to your business models.Understand simple data binding: URL centric data mapping to your action method.Interceptors: how to use them and why they are useful. We implemented a simpleinterceptor that catch all errors and send an email.

We’ve learned a lot about the internals of controllers in this chapter, and in thenext chapter we’ll build on our knowledge by implementing some fine-lookingviews to give our warehouse application some visual sizzle.

6.6 Summary

131

©Manning Publications Co. Please post comments or corrections to the Author Online forum: http://www.manning-sandbox.com/forum.jspa?forumID=811