Play Framework Trainning

51
Play! Framework Keuller Magalhães [email protected] www.playframework.com.br 2013

Transcript of Play Framework Trainning

Play! Framework

Keuller Magalhães

[email protected]

www.playframework.com.br

2013

2

Agenda

Arquitetura de Componentes

Estrutura da Aplicação

Rotas e Controladores

Modelos

Views

Distribuição

3

Agenda

Arquitetura de Componentes

Projeto

Rotas e Controladores

Modelos

Views

Distribuição

4

Arquitetura de Componentes

HTTP

Routes

Cotroladores

Model ModelHTML XML JSON

Baseada em padrões:

● MVC

● Page Controller

● Separation of Concern

● DRY

● Active Record

● Low Coupling

● High Cohesion

● Single Responsability

● Interface segregation

● Dependency Inversion

● YAGNI

5

Arquitetura de Componentes

● Componentes:● Rotas (URLs)

● Controladores (fluxo)

● Modelos (entidades)

● Templates (views)

● Extensão através de plugins

● Suporte a aplicações modulares

6

Agenda

Arquitetura de Componentes

Estrutura da Aplicação

Rotas e Controladores

Modelos

Views

7

Estrutura da Aplicação

Precisa de uma versão do Java 1.6+

Podemos fazer o download do Play!

www.playframework.org

Devemos descompactá-lo numa pasta

Adicionamos o caminho da pasta no classpath do

sistema

8

Estrutura da Aplicação

Acessando o console do Play!$ play

Para compilar nossa aplicação, basta digitar

$ compile

Para executarmos a aplicação, basta digitar:

$ run

Apontamos o navegador para a URL:

http://localhost:9000/

9

Estrutura da Aplicação

10

Estrutura da Aplicação

Limpando código do projeto

$ clean

Preparando projeto para Eclipse/IDEA

$ eclipse | idea

Executando os testes automatizados

$ test

Preparando a aplicação para implantação

$ clean compile stage

Atualizando as dependências do projeto

$ update

11

Agenda

Arquitetura de Componentes

Projeto

Rotas e Controladores

Modelos

Views

Distribuição

12

Rotas e Controladores

Rotas são mapeamentos entre URL e controladores

O arquivo conf/routes contem a definição de

todas as rotas de sua aplicaçãoGET   /     controllers.Application.index()

Esse mapeamento nos dá três informações:

Método HTTP usado GET

Caminho da requisição /

Método de ação index() da classe Application

13

Rotas e Controladores

Play suporta todos os métodos HTTP do protocolo GET, POST, PUT, DELETE, OPTIONS, HEAD, etc

Formato da URI

URI estática

GET    /list    controllers.Cliente.list()

URI dinâmicaGET    /edit/:id   controllers.Cliente.editar(id: Integer)

URI abrangenteGET   /imagem/*arquivo   controllers.Util.imagem(arquivo)

14

Rotas e Controladores

URI com parâmetros fixos

GET   /   controllers.Teste.show(page = “index”)

URI com parâmetros padrãoGET   /    controllers.Teste.show(page ?= “index”)

Prioridade entre as Rotas As primeiras rotas na declaração terão prioridade perante as

demais

Todas as rotas são compiladas no objeto routes, podendo

acessá-las via código Java, da seguinte forma:

routes.Application.index()

15

Rotas e Controladores

Play! é um framework MVC (baseado em ação)

Um controlador é uma classe Java dentro do pacote

controllers e que estende a classe Controller

Uma ação é um método público estático que retorna

um objeto Result Tipos de Result:

ok()

redirect()

notFound()

badRequest()

status()

16

Rotas e Controladores

Vejamos o controlador padrão:

package controllers;

import play.*;import play.mvc.*;import views.html.*;

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

17

Rotas e Controladores

Vamos definir as rotas para nossa aplicação

# ponto de entrada da aplicacaoGET    / controllers.Application.index()

# CRUD tarefasGET /tarefas controllers.TarefaController.lista()POST /tarefas controllers.TarefaController.criar()POST /tarefas/excluir/:idcontrollers.TarefaController.excluir(id: Int)

Temos 3 rotas, sendo que:primeira: lista as tarefas existentes

segunda: cria uma nova tarefa

terceira: remove uma tarefa pelo id

18

Rotas e Controladores

Vamos definir a classe controladora

public class TarefaController extends Controller {

   public static Result lista() {      return TODO;   }

   public static Result criar() {   return TODO;

   }

   public static Result excluir(Integer id) {      return TODO;   }}

TODO é um tipo de retorno 501 Not Implemented, útil durante o desenvolvimento.

19

Rotas e Controladores

Se executarmos nossa aplicação, veremos

20

Agenda

Arquitetura de Componentes

Estrutura da Aplicação

Rotas e Controladores

Modelos

Views

Distribuição

21

Modelos

Um objeto de modelo é na verdade um POJO

O modelo pode ser usado como uma

representação da uma entidade do banco de dados

Play! oferece suporte a dois mecanismos de

persistência (ORM):

Ebean

JPA

A configuração padrão usa Ebean ORM

22

Modelos

Criando nosso objeto de modelo

public class Tarefa {public Integer id;public String descricao;

public static List<Tarefa> readAll() {   return new ArrayList<Tarefa>();}

public static void create(Tarefa bean) {}

public static void delete(Integer id) {}

}

23

Modelos

Por padrão Play! usa o banco H2 embarcado

Para utilizarmos o MySQL5, precisamos do driver

Edite o arquivo project/Build.scala

val appDependencies = Seq(   “mysql” % “mysql­connector­java” % “5.1.25”,   javaCore,   javaJdbc,   JavaEbean)

24

Modelos

Configurando nossa conexão com banco de dados

Edite o arquivo conf/application.conf

db.default.driver=”com.mysql.jdbc.Driver”db.default.url=”jdbc:mysql://localhost/play”db.default.user=rootdb.default.password=”admin123”

Para ativar o controle do Ebean, devemos descomentar

ebean.defaults=”models.*”

Precisamos transformar nosso modelo numa entidade persistente

25

Modelos

Adaptando nossa classe de modelo

@Entitypublic class Tarefa extends Model {

@Idpublic Integer id;

@Column(length=35)public String descricao;

public static Finder<Integer,Tarefa> finder =    new Finder(Integer.class, Tarefa.class);

...}

26

Modelos

Implementando os métodos de persistência

@Entitypublic class Tarefa extends Model {

...        public static List<Tarefa> readAll() {           return finder.all();        }

        public static void create(Tarefa bean) {           bean.save();        }

        public static void delete(Integer id) {           finder.ref(id).delete();        }

}

27

Modelos

Para suporte a transações devemos usar a anotação @Transactional

public class TarefaController extends Controller {

@play.db.ebean.Transactional        public static void criar() {           ...        }

}

Devemos usar a anotação @Transactional quando temos operações de escrita Em operações de leitura devemos usar o atributo readOnly=true na anotação @Transactional

28

Agenda

Arquitetura de Componentes

Estrutura da Aplicação

Rotas e Controladores

Modelos

Views

Segurança

Distribuição

29

Views

Uma é um template de página HTML com código de

script Scala

Todo template é compilado em byte code

Todo template deve estar contido na pasta views Todo template deve ter a extensão .scala.html

Play! ainda não possui uma biblioteca de

componentes visuais para criação de interfaces

gráficas

30

Views

Vejamos o template da view →app/views/index.scala.html

@(message: String)

@main(“Welcome Play 2.0”) {

 @play20.welcome(message)

}

Neste caso estamos criando uma view, baseada

numa página de layout padrão main.scala.html

31

Views

Templates podem receber parâmetros de qualquer

tipo de dados Usamos o caracter especial @ para informar comando

Scala no template

Em nosso exemplo anterior, estamos passando um

parâmetro do tipo String, na variável message

@(message: String)

32

Views

O mecanismo de templates do Play! nos permite

reutilizar outros templates views bases para as páginas da aplicação

Em nosso exemplo anterior, estamos usando o

template main.scala.html como base da nossa

página

33

Views

Vejamos o código do template index.scala.html@(title: String)(content: Html)<!DOCTYPE html><html><head>    <title>@title</title>    <link rel="stylesheet" media="screen"           href="@routes.Assets.at("css/main.css")">    <link rel="shortcut icon" type="image/png"           href="@routes.Assets.at("images/favicon.png")">    <script type="text/javascript" src="@routes.Assets.at("javascripts/jquery­1.9.0.min.js")"></script></head><body>    @content</body></html>

34

Views

@(tasks: List[Tarefa], taskForm: Form[Tarefa])

@import helper._

@main("Lista de Tarefas") {    

    <h1>@tasks.size() tarefa(s)</h1>    

    <ul>

        @for(task <­ tasks) {

            <li>

                @task.descricao

                @form(routes.TarefaController.excluir(task.id)) {

                    <input type="submit" value="Delete">

                }

            </li>

        }

    </ul>

}

35

Views

No template anterior criamos um código para exibir uma lista de tarefas, bem simples Nosso template recebe dois parâmetros

uma lista de tarefas um objeto Form, baseado em nosso modelo@(tasks: List[Tarefa], taskForm: Form[Tarefa])

Logo após realizamos a importação de helpers   @import helper._

Depois usamos um comando @for() padrão para exibir os itens da coleção tasks

36

Views

● Para completar nosso template, adicionamos o código a seguir:    <h2>Criar tarefa</h2>

    @form(routes.TarefaController.criar()) {

        @inputText(taskForm("descricao")) 

        <input type="submit" value="Create">

    }

No trecho acima criamos um formulário usando o helper @form() O helper recebe como argumento a rota da ação que deverá ser invocada, quando o formulário for submetido Também usamos o helper @inputText() para criar uma caixa de texto baseada num campo do formulário

37

Views

Implementando o método de ação lista()

public class TarefaController extends Controller {   static Form<Tarefa> taskForm = Form.form(Tarefa.class);

   // exibe a pagina index.scala.html passando dois    // parametros: List<Tarefa> e Form<Tarefa>   public static Result lista() {      return ok(views.html.index         .render(Tarefa.readAll(), taskForm));   }

   ...}

38

Views

Implementando o método de ação criar()

public class TarefaController extends Controller {

   public static Result criar() {      Form<Tarefa> form = taskForm.bindFromRequest();      if (form.hasErrors()) {         return badRequest(index.render(                    Tarefa.readAll(), form));      }

      Tarefa.create(form.get());      return redirect(routes.TarefaController.lista());   }

   ...}

39

Views

Implementando o método de ação excluir()

public class TarefaController extends Controller {

   public static Result excluir(Integer id) {      Tarefa.delete(id);      return redirect(routes.TarefaController.lista());   }

}

40

Views

Podemos utilizar qualquer dado armazenado na sessão

do usuário para renderizar na view

public class TarefaController extends Controller {   public static Result showInfo() {      session(“usuario”, “Administrador”);      session(“email”, “[email protected]”);      return ok(views.html.showUserInfo());   }}

// na view teremos@main(“Sample”) {   Usuario: @session(“usuario”) <br/>   E­mail.: @session(“email”)}

41

Views

Devemos observar alguns pontos quanto ao uso da sessão numa aplicação Play:

Os dados não são armazenados no servidor Os dados são armazenados localmente via cookie Os coolies são assinados com chave secreta que não

permite visualizar seu conteúdo Só podemos armazenar dados do tipo String A sessão não expira, ou seja, não possui timeout

42

Views

Existem formulários que não estão associados a modelos de dados

Estes formulários são dinâmicos

public static Result authenticate() {

   DynamicForm dataForm = Form.form().bindFromRequest();

   String username = dataForm.get(“username”);

   String password = dataForm.get(“password”);

   // alguma validacao

   return redirect(views.html.dashboard.render());

}

43

Agenda

Arquitetura de Componentes

Estrutura da Aplicação

Rotas e Controladores

Modelos

Views

Segurança

Distribuição

44

Segurança

Criamos um mecanismo de segurança util e simples

usando a classe Authenticator

import play.mvc.Security;

public class Secured extends Security.Authenticator {

   public String getUsername(Context ctx) {      return ctx.session().get(“username”);   }

   public Result onUnauthorized(Context ctx) {      return redirect(routes.LoginController.form());   }}

45

Segurança

Usamos a anotação @Authenticated para proteger

nossos controladores ou métodos de ação

import play.mvc.Security;

@Security.Authenticated(Secured.class)public class Application extends Controller {   ...}

public class Application extends Controller {

   @Security.Authenticated(Secured.class)   public static Result admin() {      ...   }}

46

Agenda

Arquitetura de Componentes

Estrutura da Aplicação

Rotas e Controladores

Modelos

Views

Segurança

Distribuição

47

Distribuição

Play suporta dois tipos de distribuição: Distribuição direta via runtime Distribuição via WAR (container JavaEE)

Para distribuirmos uma aplicação Play de forma direta, precisamos gerar seu runtime, através:

$ play clean compile stage

Posteriormente basta executar o script start$ target/start ­Xms256m ­Xmx256m ­Xss1m

Os parâmetros de memória são opcionais

48

Distribuição

Para implantarmos num contaier JavaEE, devemos utilizar

um plugin chamado play2war

https://github.com/dlecan/play2-war-plugin No arquivo project/plugins.sbt adicione a seguinte linha

addSbtPlugin("com.github.play2war" % "play2­war­plugin" % "1.0")

No arquivo project/Build.scala adicione a seguinte linha

import com.github.play2war.plugin._

49

Distribuição

Ainda no arquivo project/Build.scala adicione a seguinte

linha, nas configurações do projeto adicioneval main = play.Project(appName, appVersion, appDependencies)   .settings(Play2WarPlugin.play2WarSettings: _*)   .settings(      Play2WarKeys.servletVersion := “2.5”,      Play2WarKeys.targetName := Some(“tarefas”)

   )

No console do Play, digite$ war

Para deploy dentro do Jboss, requer algumas configurações especiais (veja na doc do plugin)

50

Anexo I – Ebean API

Implementando consultas

1. Lista todos os objetos: Aluno.finder.all()

2. Pesquisa pelo ID: Aluno bean = Aluno.finder.byId(5);

3. Pesquisa condicional:Aluno.finder.where()   .ilike(“nome”, “%ana%”)   .orderBy(“nascimento desc”)   .findList();

4. Pesquisa por propriedade:Aluno bean = Aluno.finder.where()   .eq(“status”, Status.ATIVO)   .orderBy(“nome asc”)   .findList();

51

Keuller Magalhães

[email protected]

www.playframework.com.br