Play je framework sloužící k tvorbě webových aplikací běžících nad JVM a postavených na architektuře MVC. Je založen na principech REST a důraz klade na bezstavovost jednotlivých aplikací. Jako jazyk umožňuje programátorům zvolit Javu nebo Scalu, o kterou programátor i při vývoji v Javě často zavadí, jelikož je na pozadí celého frameworku a je mimo jiné použita i jako šablonovací jazyk.
Protože Scala je zpětně kompatibilní s Javou, lze jednotlivé Java objekty používat i ve Scale. Teoreticky je tak možné celou modelovou část aplikace napsat v Javě a na řadiče a pohledy použít Scalu.
Jedná se o kompletní framework, který přichází s vestavěnou databází H2, vlastním ORM nástrojem Ebean a vlastním serverem Netty, na kterém lze aplikace během vývoje spouštět. Díky svému charakteru je často srovnáván s podobně zaměřenými frameworky, jako jsou Nette Framework, Django, Symfony nebo Ruby on Rails, a díky svým vlastnostem se hodí pro vývoj menších a středně velkých aplikací. V Play je spojen charakter vývoje typický pro podobné frameworky – rychlost, jednoduchost a lehkost a svět Javy, který je dnes vedle .NET frameworku standardem pro enterprise aplikace.
V praxi je framework používán kromě jiných firmami Linkedin nebo britským listem The Guardian.
Jedná se o open source nástroj, jehož vývoj zastřešuje společnost Typesafe. K dispozici je kromě dokumentace pro Javu i Scalu také množství ukázkových aplikací. Co se týče dalších zdrojů informací, je možné sáhnout po zahraniční literatuře. Příkladem publikací jsou Play for Java , Play for Scala a další.
Instalace a zprovoznění frameworku
Základním předpokladem pro používání frameworku je správně nainstalovaná Java. Jeho zprovoznění je pak otázkou několika minut. Celý framework má zhruba 1,17MB. Po jeho stažení je třeba celý archiv rozbalit na libovolné místo na disku. K tomuto adresáři je třeba nastavit práva pro čtení a zápis, protože během spuštění si zde framework ukládá pomocné soubory. Posledním krokem instalace je úprava systémové proměnné PATH. Potom, co je v systému nastavena cesta k adresáři s frameworkem, je zpřístupněn také příkaz activator.
Volba IDE Přestože Play nenutí programátory k používání konkrétního IDE, jeho volba je do jisté míry ovlivněna zvoleným jazykem. I tak je ale možné pracovat v prakticky jakémkoli textovém editoru. Co se týče třech nejpoužívanějších vývojových prostředí pro Javu, framework nalezne podporu v Eclipse, Netbeans i IntelliJ Idea, a to již přímo nebo po instalaci dodatečných pluginů. Pro práci se Scalou je možné použít i nástroj Scala IDE, který je postavený nad Eclipse.
Hello world Pro generování základní struktury projektu je možné z konzole spustit příkaz activator new za kterým se uvede název vytvářené aplikace. Následně je možné zvolit jazyk, ve kterém bude aplikace vytvářena. Vybrat je možné mezi Javou a Scalou. V aktuální složce je poté vytvořen adresář se zadaným názvem a základní strukturou aplikace.
├──app │ ├──assets │ │ ├──stylesheets │ │ └──javascripts │ ├──controllers │ ├──models │ ├──views ├──conf │ ├──application.conf │ └──routes ├──public │ ├──stylesheets │ ├──javascripts │ └──images ├──project │ ├──build.properties │ └──plugins.sbt ├──libs ├──logs │ └──application.log ├──target └──test
Nastavení aplikace Základním konfiguračním souborem aplikace je soubor application.conf. Jedná se o běžný textový soubor, používající formát HOCON a jeho úpravou je možné měnit nastavení databázového připojení, konfiguraci nástroje Ebean, logování, nebo vlastnosti lokalizace. Základní konfiguraci databáze a ORM nástroje lze provést odkomentováním několika řádků. #Database conf db.default.driver=org.h2.driver db.default.url="jdbc:h2:mem:play" db.default.user=sa db.default.password=""
#Ebean conf ebean.default="models" Za sestavení celé aplikace je odpovědný nástroj zvaný Scala Build Tool (sbt). Ten se stará o veškeré závislosti, jejich stažení, integraci a sestavení výsledné aplikace.
import play.PlayJava
name := """sqatool""" version := "1.0-SNAPSHOT" lazy val root = (project in file(".")).enablePlugins(PlayJava) scalaVersion := "2.11.1"
libraryDependencies ++= Seq( javaJdbc, javaJpa, "org.hibernate" % "hibernate-entitymanager" % "4.2.5.Final", "postgresql" % "postgresql" % "9.1-901-1.jdbc4", cache, javaWs, "com.adrianhurt" %% "play-bootstrap3" % "0.4", "org.mindrot" % "jbcrypt" % "0.3m" )
Základní příkazy konzole Jednou možností, jak framework používat je z příkazového řádku, druhou je pak webové rozhraní. V dřívějších verzích frameworku byl pro práci s ním vyhrazen příkaz play. Ten je od verze 2.3.6 (v době psaní tohoto článku je nejnovější verze 2.3.9) nahrazen příkazem activator. Kompletní seznam příkazů lze pak vypsat pomocí activator help.
Tvorba modelu Modelová část aplikace se odvíjí od zvoleného jazyka, v případě Javy jsou jednotlivé objekty modelu klasické Java soubory. Za kontroverzní vlastnost frameworku lze na první pohled označit to, že umožňuje deklarovat jednotlivé atributy tříd jako veřejně přístupné a dochází tak k porušení zapouzdření, jedné ze základních objektových vlastností.
Ve skutečnosti se ale autoři Play frameworku snažili programátorům maximálně ulehčit práci. V tomto případě zpřehlednit kód a zmenšit množství psaného / generovaného kódu. Přestože to tak nevypadá, při překladu jsou ke každému veřejnému atributu vygenerovány přístupové metody a práce s atributy je pak prováděna přes tyto metody. Některé frameworkzy (například Hibernate) přístupové metody vyžadují. Nic tak nebrání tomu, aby se od počátku v kódu tyto metody vyskytovaly a jednotlivé atributy byly označeny jako neveřejné (příp. soukromé).
Uvnitř modelových objektů je možné použít JPA anotace. ORM nástroj Ebean, který je součástí frameworku registruje mapované objekty s pomocí anotace @Entity. Aby mohly jednotlivé objekty využívat vlastností nástroje Ebean, měly by dědit ze třídy play.db.ebean.Model. @Entity public class Delivery extends Model{
@Id public Long id; public String name; public String description; public BigDecimal price; @ManyToOne public Tax tax; @ManyToMany(mappedBy = “deliveries”) public List<Payment> payments; @OneToMany public List<Purchase> purchases;
public Delivery(String name, String description, BigDecimal price, Tax tax){ // tělo konstruktoru
public static Finder<Long, Delivery> getFinder(){ return new Finder<Long, Delivery>(Long.class, Delivery.class);
// další metody
Tvorba řadičů a mapování HTTP požadavků Controllery (Model-view-controller) jsou ve webových aplikacích postavených na architektuře MVC místem, kde jsou zpracovány jednotlivé HTTP požadavky. Jsou tak vstupním a výstupním místem aplikace a propojením dalších dvou vrstev – modelu a jednotlivých pohledů.
Ve frameworku Play jsou to pak objekty dědící od třídy play.mvc.Controller. Každý takový objekt řadiče obsahuje několik statických metod, jejichž úkolem je zpracovat příchozí HTTP požadavek a vrátit instanci třídy play.mvc.Result. Mapování jednotlivých HTTP požadavků je prováděno uvnitř souboru conf/routes. Uvnitř každé definice je HTTP požadavek na konkrétní adresu přiřazen ke konkrétní metodě konkrétního řadiče.
#Home page GET / controllers.ApplicationController.index() #Product GET /product/:id controllers.ProductController.show(id : Long) GET /product/all controllers.ProductController.showAll() POST /product/new controllers.ProductController.createNewProduct()Jednotlivé definice mohou kromě statických částí obsahovat i další parametry. Protože je Scala silně typový jazyk, je nutné u každého parametru uvést i jeho datový typ.
Reverse routing Proces směrování jednotlivých požadavků je možné provádět i opačným směrem. Jedná se o situaci, kdy nejprve dojde k zavolání metody řadiče, která místo play.mvc.Result vrátí objekt play.mvc.Call, čímž daný HTTP požadavek vyvolá. Po překladu je ze souboru conf/routes vygenerován objekt Routes, který tyto obrácené definice obsahuje.
Doba platnosti a soubory Cookies Protokol HTTP je ze své podstaty bezstavový, takže data, která jsou uvnitř jednoho požadavku předávána, jsou po zpracování požadavku ztracena. Pro ukládání stavů aplikace mezi jednotlivými požadavky tak slouží soubory HTTP cookie. Soubory cookies jsou obyčejné textové soubory – obsahují text a jejich velikost je omezena na 4Kb, které HTTP server ukládá na straně klienta. Tyto soubory mohou obsahovat různé textové informace, na které se lze v případě potřeby odvolávat mezi jednotlivými HTTP požadavky. U jednotlivých cookies lze také nastavit dobu, po kterou je má server na straně klienta držet.
Doba platnosti se liší podle potřeby. Nejkratším úsekem, který lze v Play definovat je Request. Data s touto platností jsou k dispozici přesně po dobu existence jednoho HTTP požadavku. Další možností je Flash, která data udržuje při životě přesně po dobu dvou HTTP požadavků. To je například doba nutná k zaslání informačních výpisů při odesílání formulářů nebo přesměrování mezi dvěma stránkami. Doba platnosti Session udržuje data do chvíle, než uživatel ukončí prohlížeč a jedná se o nejdelší časový úsek, který lze v Play aplikaci definovat. Poslední možností je pak doba platnosti Response, kterou lze použít například pro úpravu podoby odpovědi HTTP protokolu.
Implementace pohledů Pohledy (Views) jsou vrstvou MVC architektury, která má za úkol prezentovat data uživateli v čitelné a srozumitelné formě. Ve webových aplikacích jsou to často soubory s koncovkou .html, které lze ale díky použití dalších jazyků dynamicky generovat. V prvních verzích Play frameworku byl tímto šablonovacím jazykem Groovy, který byl později nahrazen Scalou.
Každá šablona může, kromě instrukcí značkovacího jazyka definujícího statickou strukturu stránky, obsahovat ještě sadu dalších jazykových konstrukcí pro generování dynamického obsahu. Jedná se o podmínky, cykly nebo části jiných šablon. Každá takto definovaná dynamická část je ve výsledku přegenerována na statický výstup. Nevýhodou takového přístupu je, že se tento proces generování provádí při každém požadavku o tuto stránku. Play tento nedostatek řeší tím, že každou stránku generuje pouze jednou již při překladu, čímž zobrazení jednotlivých stránek urychluje. Během překladu dochází také ke kontrole správnosti jednotlivých typů dat a případnou chybu lze tak odhalit již během překladu.
Šablony ve frameworku Play jsou soubory s koncovkou .scala.html a jsou umístěné v adresáři app/views. Každou šablonu je třeba chápat jako funkci a její použití lze provést zavoláním dané funkce.
Formuláře a data binding Práce s formulářem obvykle vyžaduje dva základní kroky. Prvním je formulář uživateli zobrazit, druhým potom zajistit jeho odeslání zpět do aplikace, včetně ověření jeho obsahu. Formuláře jsou ve frameworku Play objekty typu play.data.Form. Základem pro každý formulář je vždy některá třída z modelu, jehož data se mají s pomocí formuláře získat. K vytvoření formulářového objektu stačí v odpovídajícím řadiči implementovat metodu, která objekt formuláře pošle společně s dalšími požadovanými daty do dané šablony.
public static Result showLoginFormPage(){ return ok(views.html.login.render(form(Customer.class), "Login")); }Po zavolání metody render je dané šabloně předán objekt formuláře. Každou šablonu lze chápat jako objekt (funkci) – lze jí předávat parametry a volat její metody.
@helper._ @(loginForm : Form[models.Customer], title : String) @main(title : String){ <div id="content"> @form(action = routes.User.authenticate(), 'id -> "loginForm"){ <h3>Přihlášení</h3> <table> <tr> <td><title for="user">Jméno: </title></td> <td><input type="text" id="user" name="user" /></td> </tr> <tr> <td><title for="password">Heslo: </title></td> <td><input type="password" id="password" name="password" /></td> </tr> </table>
</div>