“Tão fácil que nem parece Java...”
Minicurso
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
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
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
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)
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
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)
Porque o Play?
Cases do Play
O Play por aí...
O Play por aí...
O Play por aí...
Material para estudo
Documentação!!!
http://migre.me/kVMXChttp://migre.me/kVN3h
http://migre.me/kVRLf
http://migre.me/l8D5M
Documentação!!!
Comparações
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!!
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!!
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!!
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!
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
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!
Estrutura da aplicação
Classes controllers
Templates HTML
Classes de teste
Arquivo de configuração do sistemaArquivo de rotas do sisema
Arquivos estáticos
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
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
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
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?
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:
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
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
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)
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()
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)
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!
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)
Templates com Scala
Observe a view main.scala.html:
@(title: String)(content: Html)
<!DOCTYPE html>
<html>
<head>
<title>@title</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>
@content
</body>
</html>
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>
}
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>
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>
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!
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...
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
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...
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
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árioque contém
carrosAqui é criado usando um objeto Form
Um formulário já com todos osAtributos da classe Carro
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());
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
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
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
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
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>
}
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!"));
}
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 umforeach e funciona
exatamente como um...
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 encontraa lista de todos
os carros pra você!=D
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 passandoo id do carro que
queremos detalhar
Vou receber um idJunto com a URL
Passando o idpara a action
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!
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
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
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 parachamar uma action sem ser pelo arquivo routes
Obrigado!