O documento fornece informações sobre um minicurso sobre o framework Play para desenvolvimento web Java. O minicurso terá duração de 3 horas e ensinará os conceitos básicos do Play para que os participantes possam construir uma aplicação simples de CRUD. O documento explica características do Play como arquitetura, facilidade de uso, templates em Scala e casos de uso reais.
2. Sobre mim...
➔
Wandesson Soares
➔
Graduando em Sistemas para Internet no IFPB –
Campus João Pessoa
➔
Estagiário de desenvolvimento web da SEDES – TRE/PB
➔
Desenvolvedor web – Java EE, PHP e Android
➔
Entusiasta do Software Livre (but not hater)
➔
Gosto de compartilhar conhecimento
3. Sobre o minicurso
➔
Duração: 3h
➔
Resumo: Fornecer a base para o desenvolvimento com
o Play Framework
➔
Não é um curso completo
➔
Objetivo: Fazer uma aplicação que faça um CRUD
simples
4. O que é o Play?
➔
Criado pela em 2007 pela Znexity, posteriormente
absolvido pela Typesafe
➔
Baseado na arquitetura WOA
➔
Propõe simplicidade, produtividade, performance e
escalabilidade
➔
Um framework que redefine o desenvolvimento web
com Java
➔ Também dá suporte ao Scala
➔
Curva de aprendizado muito baixa
➔
Usufrui de todo o poder da Java Virtual Machine!
➔
Fortemente inspirado no Rails e no Django
5. O que não é o Play?
➔
Não é um framework padrão Java EE (Struts, Spring,
Vraptor)
➔
Não segue a especificação
➔
Não é apenas um framework. É uma solução completa
para o desenvolvimento web (full-stack framework
web)
6. Porque o Play?
➔
Porque já sabemos Java...
➔
Servidor integrado (JBoss Netty)
➔
RESTful por default
➔
ORM integrado (Ebean)
➔
Suporte nativo a configuração de ambiente de teste,
homologação e produção
➔
Engine de templates em Scala = Views compiladas
➔
Sem redeploy, um F5 resolve tudo! (puts!)
➔
Heroku dá suporte a aplicações Play
7. Porque o Play?
➔
Desenvolvimento amigável: simples, produtivo e
divertido
➔
Suporte a programação assíncrona
➔
Pode ser usado em aplicações Real Time
➔
Suporte a tecnologias: HTML5, LESS, CoffeScript,
Websocket, etc
➔
Gerenciador de dependências integrado - SBT
➔
Ambiente performático e escalável
➔
Traz de forma nativa suporte a testes (JUnit, Selenium,
etc)
15. Instalando o Play - Windows
Pré-requisito: JDK instalado.
➔
Faça o download do Play -
http://www.playframework.org/
(Nesse minicurso é usada a versão 2.2.3)
➔
Descompacte na raiz do disco c:
➔
Para facilitar, renomeie a pasta para apenas 'play'
➔
Adicione c:play no path das variáveis de ambiente
➔
Abra o terminal e digite: play
➔
Have fun!!
16. Instalando o Play – Linux
Pré-requisito: JDK instalado.
➔
Faça o download do Play - http://www.playframework.org/
(Nesse minicurso é usada a versão 2.2.3)
➔
Descompacte em diretório de sua preferência e para facilitar, renomeie a
pasta para apenas 'play'
➔
Torne o play executável digitando no terminal o comando:
➔
chmod a+X $caminhodoplay/play
➔
Adicione o Play no path:
1. Abra o arquivo com o comando: sudo gedit ~/.bashrc
2. No final do arquivo adicione a linha: export
PATH=$PATH:/caminhodoplay/play
3. Salve o arquivo e no terminal execute o comando: source ~/.bashrc
➔
Execute o play no terminal com o comando: play
➔
Have fun!!
17. Instalando o Play – MacOS
Pré-requisito: JDK instalado.
➔
Faça o download do Play - http://www.playframework.org/
(Nesse minicurso é usada a versão 2.2.3)
➔
Descompacte em diretório de sua preferência
➔
Para facilitar, renomeie a pasta para apenas 'play'
➔
Torne o play executável digitando no terminal o comando:
➔
chmod a+x $caminhodoplay/play
➔
Adicione o Play no path, para isso, basta adicionar o diretório
$HOME/play/ no arquivo /etc/paths
➔Se preferir o Homebrew apenas rode o comando: brew install play
➔
Execute o play no terminal com o comando: play
➔
Have fun!!
18. Primeira aplicação
➔
Escolha uma pasta para salvar a aplicação
➔
Execute play new <nome-da-aplicação>
➔
Confirme o nome da aplicação (Enter) ou troque
digitando o novo nome e apertando Enter
➔
Escolha a opção 2 – Create a simple Java application
➔
Have fun!
19. Rodando a aplicação
➔
Para rodar a aplicação, vá para a pasta da aplicação
através do terminal (cd nome-da-aplicação) e use o
comando: play run
➔
Acesse: localhost:9000
➔
Para parar o servidor use o atalho Ctrl + D no terminal
20. Configure para o Eclipse
➔
No play console use o comando eclipse
➔
Importe o projeto no eclipse
➔ Obs: Use a perspectiva Java e não Java EE
➔
Have fun!
21. Estrutura da aplicação
Classes controllers
Templates HTML
Classes de teste
Arquivo de configuração do sistema
Arquivo de rotas do sisema
Arquivos estáticos
22. Let's play à vera...
➔
O que vamos fazer?
➔ Uma aplicação que faça um CRUD simples de carros
➔
O que vamos aprender com essa aplicação?
➔
Como funciona a navegação
➔
Como criar as views
➔
Como funcionam os controllers
➔
Como recuperar dados das views
➔
Como setar parâmetros e passar para as views
➔
Como persistir os dados
23. Criando a aplicação turmas
➔
Crie um workspace para o play. Geralmente
c:java/workspaceplay
➔
No terminal, vá até a pasta do workspace pelo terminal
e crie a aplicação: play new carros
➔
Entre na pasta da aplicação pelo terminal: cd carros
➔
Configure a aplicação para o eclipse
➔
Importe a aplicação no eclipse
24. Como funciona a navegação?
➔
Tudo concentrado em um único arquivo: conf/routes
➔
A configuração é feita em 3 partes:
1. Método HTTP (GET ou POST)
2. URL da aplicação
3. Action que vai tratar a requisição
Exemplo:
GET /home controllers.Application.index()
➔
Ao digitar localhost:9000/home será executado o
código que está no action index() de Application
25. Como funcionam as views?
➔
Simples html
➔
Deve seguir o padrão: nomedoarquivo.scala.html
➔
Deve ser colocado dentro do pacote app/views
➔
Mas por quê esse nome escala no nome?
➔
O Play utiliza Scala para escrita de páginas dinâmicas
➔
O JSP tem EL, o Play tem Scala.
➔
O play transforma a view numa classe, ou seja, no Play,
as views também são compiladas. Vantagens?
26. Adicionando o bootstrap
➔
Baixe o Bootstrap (http://migre.me/kVTSQ)
➔
Descompacte em pasta de sua preferência
➔
Copie a pasta descompactada
➔
Cole na pasta public da nossa aplicação, de modo que
fique como apresentado abaixo:
27. A view home.scala.html
➔
Crie um novo arquivo html com esse nome em
app/views
➔
Pegue o código aqui: http://migre.me/kVHHa
28. Renderizando a view
➔
A seguir, vamos entender melhor o funcionamento dos
controllers, mas, por enquanto, vá no Application.java e
mude isso:
return ok(index.render("Your new application is ready."));
para isso:
return ok(views.html.home.render());
➔
Ignore os erros do Eclipse e acesse novamente a
aplicação
➔
Dê um F5 na pasta do projeto no Eclipse para os erros
sumirem
29. Como funcionam os controllers?
➔
Ficam em app/controllers
➔
Herdam da classe Controller do Play
➔
Obs: Cuidado com os imports, o pacote play.api é do Scala. No
mundo Java usamos sempre play.mvc
➔
São acionados para fazer alguma operação antes de
renderizar uma view
➔
Seus métodos seguem 3 regras:
1. Devem ser públicos
2. Devem ser estáticos
3. Retornam um objeto do tipo Result (ou uma subclasse dele)
30. Nosso próprio controller
➔
Crie uma classe Java chamada CarrosController
➔
Lembre-se das regras de um controller!
➔
Desfaça o que você fez em Application.java
➔
Faça o mesmo que você tinha feito em Application.java
só que agora no controller CarrosController.java
➔
Altere a rota da página inicial padrão do Play para que
só seja exibida quando o usuário acessar /play
➔
Troque o nome da action index() para home()
➔
Adicione uma rota para que quando o usuário acesse a
raiz da aplicação direcione para a action home()
31. Entendo o código da action
public static Result home() {
return ok(views.html.home.render());
}
➔
Quando retornamos ok passamos para o cabeçalho
HTTP o código de status 200 (vide códigos de status
HTTP)
➔
Quando a view é compilada, é gerada uma classe que
contém o método render() que renderiza a view
➔
Para acessarmos uma view no controller basta usar:
views.html.nomedaview (sem .scala.html)
32. Passando parâmetros para as views
➔
O método render(), que é gerado quando a view é
compilada, é dinâmico, portanto:
➔
0 parâmetros na view, 0 parâmetro no render()
➔
1 parâmetro na view, 1 parâmetro no render()
➔
2 parâmetros na view, 2 parâmetros no render()
➔
Tudo é definido primeiramente na view
➔
E como eu adiciono um parâmetro na view?
➔
Usando Scala!
33. Passando parâmetros para as views
➔
Vou ter que aprender Scala? Não... Só o básico! E
acredite... É muito fácil!
➔
Tudo em Scala começa com @ assim como em PHP
começa com <?
➔
Para definir um parâmetro é usada essa sintaxe:
@(nomedoparametro:tipo)
➔
E se caso precisar de mais de um?
@(nomedoparametro:tipo)(outro:tipo)
35. Templates com Scala
➔
São definidos dois parâmetros: título (String) e
conteúdo (Html)
➔
O tipo Html parece óbvio, suporta conteúdo Html
➔
Toda estutura Html pode ser reutilizada em outras
views, basta passar o título e conteúdo
➔
Para usar o template @main na nossa view home,
basta passar os parâmetros que o template exige:
@main(“Turmas-Home”){
<h3>Bem-vindo<h3>
}
36. Templates com Scala
Dessa forma, a nossa view resultaria no código abaixo:
<!DOCTYPE html>
<html>
<head>
<title>”Turmas-Home”</title>
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
<script src="@routes.Assets.at("javascripts/jquery-1.9.0.min.js")" type="text/javascript"></script>
</head>
<body>
<h3>Bem-vindo</h3>
</body>
</html>
37. Criando um novo template
➔
Crie um template chamado meutemplate.scala.html
que tenha a mesma estrutura da home
➔
Adicione 2 parâmetros:
➔
titulo, do tipo String
➔
conteudo, do tipo Html
➔
Coloque no title o valor @title e após o barra de menu
o @conteudo
➔
Altere o Home para usar meuTemplate, passe o título
“Turmas – Home” e o conteúdo <h3>Bem vindo</h3>
38. A view cadastrarcarro.scala.html
➔
Vá no dropbox e pegue o código: http://migre.me/kVHHa
➔
Observe que o valor do action do form: “/salvarcarro”
➔
Observe também que o método usado é POST
➔
Vá em meutemplate e altere o link do menu Cadastrar Carro,
para que quando o usuário clicar seja direcionado para essa
view
➔
Configure no routes a action
controllers.CarrosController.salvar() para essa URL
➔
Deu erro? Claro!
➔
Crie a action com o conteúdo: return TODO;
➔
Tente salvar uma turma
➔
Pelo menos os erros na tela do Play são mais bonitos!
39. A view cadastrarcarro.scala.html
➔
Crie a action com o conteúdo: return TODO;
➔
O TODO evita o erro, pois ele informa para o Play que essa
action ainda será implementada
➔
Tente salvar uma turma novamente e veja o resultado
➔
Perceba que pelo menos os erros e avisos no Play são
mais elegantes...
40. Recuperando dados do formulário
➔
Na action salva() recupere o request:
Request request = request();
➔
Recupere o parâmetro, por exemplo, o nome, e
imprima no console do Play:
System.out.println(
request.body().asFormUrlEncoded().get("marca")[0]);
➔
Teste para outros parâmetros
41. Recuperando dados do formulário
➔
What??? Calma jovem...
➔
É de propósito! Isso mesmo! Esse mesmo código
também funciona para uma aplicação que funcione
como um serviço. O objeto request pode receber
valores em XML e JSON
➔
Mas vou ter que usar essa linha de código para cada
dado que eu recuperar do formulário? E se o formulário
tiver 50 informações? Aguarde fortes emoções mais a
frente...
42. O Bean Carro.java
➔
Crie em app um package chamado models e crie uma
classe java chamada Turma
➔
O Bean no Play deve herdar de Model (de play.mvc...)
➔
Adicione os atributos id (Long), marca(String),
modelo(String) e cor (String)
➔
Gere os gets e sets
➔
Faça o mapeamento JPA
43. Usando o objeto Form
➔
Esse objeto recupera os dados de um formulário de
maneira mais amigável
➔
Recupera todos os dados do formulário
➔
Crie uma variável global no Controller:
private static Form<Carro> carroForm = Form.form(Carro.class);
É um formulário
que contém
carros
Aqui é criado usando um objeto Form
Um formulário já com todos os
Atributos da classe Carro
44. Usando o objeto Form
➔
Dentro da action salvarCarro coloque o conteúdo:
Form<Carro> formFromRequest = carroForm.bindFromRequest();
➔
Com isso eu crio uma ligação entre o formulário que
criamos como variável global com o que virá do request
Carro c = formFromRequest.get();
➔
Aqui simplesmente instanciamos um carro com os valores do
formulário vindo do request
➔
Dê um print nos atributos
System.out.println(c.getNome());
45. Persistindo seus dados
➔
O Play usa o Ebean: Um Objeto que faz toda ligação
com o Banco de dados
➔
Basicamente a mesma ideia do Hibernate
➔
Utiliza o padrão JPA
➔
Implementação conhecida e bem divulgada
➔
Fácil de usar
46. Conectando com o BD
➔
O Play já tem internamente um BD em memória: o H2
➔
Para usá-lo basta ir no application.conf e descomentar
as seguintes linhas:
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
db.default.user=sa
db.default.password=""
➔
Adcione essa linha logo abaixo, que diz ao Play quais
entidades serão persistidas:
ebean.default="models.*" // com * dizemos que serão todas
47. Atualizando o BD
➔
Acesse novamente a aplicação
➔
O Play sinalizará o seguinte erro:
Database 'default' needs evolution!
➔
Perceba que é exibido o script da nossa tabela
➔
Basta clicar em Apply this script now e o banco de
dados será atualizado em memória e pronto para usar
➔
O mesmo processo é feito para BDs tradicionais
(MySQL, PostgreSQL, Oracle, etc) basta mudar as
configurações
48. Salvando o carro
➔
Acrescente essa linha na action:
➔
Ebean.save(c);
➔
O objeto Ebean já traz vários métodos prontos, detre eles está
o de salvar =)
➔
Tente salvar uma turma. Embora aparentemente não
tenha acontecido nada, o carro foi salvo. Acredite em
mim jovem... Não acredita? Ta bom então, vou provar
mais na frente
49. Feedback para o usuário
➔
Já sabemos o que o TODO faz, vamos tirar ele daí e
vamos ao invés de retornar ele retornar para a mesma
view cadastracarro
➔
Vamos exibir uma mensagem para o usuário. Para isso
devemos adicionar um parâmetro mensagem (String)
na nossa view que só será exibida quando a mensagem
não for vazia:
@(mensagem:String)
@meutemplate("Carros - Cadastrar Carro"){
@if(mensagem != ""){
<div class="alert alert-success">
@mensagem
</div>
}
50. Feedback para o usuário
➔
Agora toda vez que renderizamos a view cadastracarro
precisamos passar a mensagem como parâmetro:
public static Result cadastrarCarro() {
return ok(views.html.cadastracarro.render(""));
}
public static Result salvarCarro() {
Form<Carro> formFromRequest = carroForm.bindFromRequest();
Carro c = formFromRequest.get();
Ebean.save(c);
return ok(views.html.cadastracarro.render("Carro salvo com sucesso!"));
}
51. Listando os carros
➔
Crie uma view chamada carros.scala.html, esta view
precisa receber um parâmetro concorda?
➔
Em Java temos List<Carro>, em Scala, temos
List[Carro]
➔
Vamos exibir os dados em forma de tabela. Ops! Parece
que vamos ter que iterar sobre a nossa lista. E agora,
como faz?
@for(carro <- carros) {
<tr>
<td>@carro.getId()</td>
<td>@carro.getModelo()</td>
<td>@carro.getMarca()</td>
</tr>
Isso parece um
foreach e funciona
exatamente como um...
52. Listando os carros
➔
Agora configure a rota:
GET /listarcarros controllers.CarrosController.listarCarros()
➔
Altere o link do menu em meuTemplate para que ao
clicar em Listar Carros seja direcionado para /listacarros
➔
Crie o método listar() com o seguinte conteúdo:
List<Carro> carros = Ebean.find(Carro.class).findList();
return ok(views.html.carros.render(carros));
➔
Veja funcionando para crer!
O Ebean encontra
a lista de todos
os carros pra você!
=D
53. Detalhando um carro
➔
Altere a view carros para possuir um botão de detalhar
<a href="/detalhacarro/@carro.getId()">
<button class="btn">
<i class="icon-search"></i> Detalhar
</button>
</a>
➔
Como fica a rota nesse caso?
GET /detalhacarro/:id controllers.CarrosController.detalhaCarro(id: Long)
Estamos passando
o id do carro que
queremos detalhar
Vou receber um id
Junto com a URL
Passando o id
para a action
54. Detalhando um carro
➔
Crie a view detalhacarro.scala.html, ela vai precisar de
um parâmetro
➔
Crie em TumasController, um método detalhaCarro()
com o seguinte conteúdo:
Carro carroselecionado = Ebean.find(Carro.class, id);
return ok(views.html.detalhacarro.render(carroselecionado));
➔
It's so easy!
55. Editando um carro
➔
Já segurei muito sua mão, tente fazer sozinho agora:
➔
Altere a view detalharcarro, colocando dois botões, um
para voltar e outro para editar
➔
Crie uma view para editar, semelhante a de cadastrar,
com um parâmetro a mais: carro
➔
Altere os campos para ficarem preenchidos. Você sabe
fazer isso!
➔
Configure a rota
➔
Altere o link do botão Editar na view detalhacarro
56. Atualizando um carro
➔
Crie uma action chamada atualizar com o seguinte conteúdo:
Carro carroselecionado = Ebean.find(Carro.class, id);
Form<Carro> atualizarForm = carroForm.bindFromRequest();
atualizarForm.get().update(id);
Carro carroatualizado = Ebean.find(Carro.class, id);
return ok(views.html.detalhacarro.render(carroatualizado));
➔
Tente entender o que faz esse código
➔
Altere o action do formulário em editarcarro para:
/atualizarcarro/@carro.getId()
➔
Configure a rota
57. Excluindo um carro
➔
Crie uma action chamada excluir com o seguinte
conteúdo:
➔
Carro carroselecionado = Ebean.find(Carro.class, id);
➔
carroselecionado.delete();
➔
return listar();
➔
Na view carros, adicione um botão Excluir
➔
Altere o href do link do botão para:
@routes.CarrosController.exlcuir(carro.getId())
Essa é a forma que podemos para
chamar uma action sem ser pelo arquivo routes