Desenvolvendo aplicações web com GWT

6,397 views
6,250 views

Published on

O Google Web Toolkit é uma ferramenta de desenvolvimento para gerar código javascript de alta performance para aplicações web através da linguagem Java, permitindo com isso a utilização de todo o poder de IDE's Java para construir aplicações web robustas e rápidas baseadas em Ajax. Esta palestra dará uma visão do funcionamento do GWT, passando por alguns conceitos importantes como requisições assíncronas, gerenciamento de histórico, construção da interface, modos de comunicação com o servidor, entre outros.

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,397
On SlideShare
0
From Embeds
0
Number of Embeds
295
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Desenvolvendo aplicações web com GWT

  1. 1. Desenvolvendo aplicaçõesweb com GWTGeraldo Augusto Massahud Rodrigues dosSantos
  2. 2. Roteiro Introdução Características Definições Hello World – Configuração e funcionamento básicos uiBinder MVP – Passive View – Supervising Controller Comunicação com servidor – RPC Conclusão 2
  3. 3. Introdução O que é o GWT? – Framework para desenvolvimento de aplicações ricas para internet (RIA) que traduz código java em código javascript. A pronúncia é gwit 3
  4. 4. Introdução Compilação [IE] .js Módulo [Firefox] .js Compilador.java GWT [Chrome] .js [Safari] .js 4
  5. 5. IntroduçãoGWT Página inicial Html Módulo completo.jsClássico Página inicial Html 5
  6. 6. IntroduçãoGWT { x:1} JSON(apenas dados)Clássico Html 6
  7. 7. IntroduçãoGWT Execução de processamento de apresentação apenas no navegadorClássico Html 7
  8. 8. Características Processamento de apresentação é todo realizado no cliente – menor uso de recursos do servidor • Escalabilidade – menor tráfego de rede • após o carregamento inicial apenas dados trafegam, pois a lógica de exibição e as telas já estão todas no cliente. 8
  9. 9. Características Codificação em Java – Orientação a objetos – Padrões de desenho – Anotações – IDE Java • Refatoração • Auto completar • Templates de código • Debug – Testes de unidade executam em Java 9
  10. 10. Características Compilador javascript – Alta performance – Múltiplos navegadores – Ofuscado – Permite utilizar javascript no código java via JSNI 10
  11. 11. Características E as desvantagens? – Tamanho do javascript inicial pode ser grande – Classes utilizadas no lado cliente devem ser ser traduzíveis para javascript • Bibliotecas de terceiros • Entidades de persistência – DTOs: lógica duplicada – Indexação • Aplicação é criada dinamicamente em javascript, portanto indexadores não a visualizam diretamente. Um trabalho extra deve ser realizado com intuito de deixá-la indexável. https://developers.google.com/webmasters/ajax- crawling/docs/html-snapshot – Código JSNI não é fácil de manter 11
  12. 12. Definições Módulo – Unidade do gwt – Definido em xml – Um módulo pode importar outros módulos – O módulo determina quais são as pastas que serão compiladas pelo compilador GWT EntryPoint – Classes que tem o método onModuleLoad executado quando um módulo é carregado – Um módulo pode possuir vários EntryPoints – Todos EntryPoints de cada módulo importado são executados Página HTML hospedeira – Página que possui a importação do javascript de um módulo 12
  13. 13. Definições Organização de pacotes – O GWT normalmente tem uma organização padronizada de pacotes, possuindo 3 sub-pacotes dentro do pacote do módulo. • client: classes que são utilizadas apenas no cliente, todas são transformadas em javascript e o código do servidor não deve normalmente utilizá-las. • server: classes exclusivas para utilização pelo servidor, o compilador GWT nem as compila para javascript, portanto nunca devem ser utilizadas no cliente. • shared: classes que podem ser utilizadas tanto no servidor quanto no cliente, normalmente são enums e classes utilitárias utilizadas em ambos os ambientes. 13
  14. 14. Hello World Módulo (HelloWorld.gwt.xml)<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web- toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt- module.dtd"><module> <inherits name="com.google.gwt.user.User" /> <source path="client" /> <source path=“shared" /> <entry-point class="com.massahud.helloworld.client.HelloWorld" /></module> 14
  15. 15. Hello World EntryPoint (com.massahud.helloworld.client.HelloWorld)package com.massahud.helloworld.client;import com.google.gwt.core.client.EntryPoint;import com.google.gwt.user.client.ui.Label;import com.google.gwt.user.client.ui.RootPanel;public class HelloWorld implements EntryPoint { @Override public void onModuleLoad() { Label labelHello = new Label("Hello world"); RootPanel.get().add(labelHello); }} 15
  16. 16. Hello World HTML Hospedeiro (helloworld.html)<!doctype html><html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>helloworld</title> <script type="text/javascript" language="javascript" src="com.massahud.helloworld.HelloWorld/com.massahud.helloworld.Hello World.nocache.js"> </script> </head> <body> </body></html> 16
  17. 17. Hello World 17
  18. 18. Hello World 18
  19. 19. Hello World Renomeando o módulo<module rename-to=“HelloWorld"> ...</module><!doctype html><html> ... <script type="text/javascript" language="javascript” src=“HelloWorld/HelloWorld.nocache.js”></script> ...</html> 19
  20. 20. Hello World 20
  21. 21. uiBinder O que é? – Framework que permite trabalhar com HTML e CSS para definir a estrutura das telas. Componentes – HTML com a estrutura das telas, permite tanto tags HTML quanto tags de componentes GWT, inclusive componentes customizados. – Classe java de mesmo nome, com vinculação automática de campos e eventos através de anotações 21
  22. 22.  Vantagens – Visualizar a estrutura da página em HTML é mais fácil do que lendo um código que a cria. – Para modificar a aparência da tela é necessário apenas modificar o HTML, a lógica continua intacta na classe java – Reuso: é fácil criar uma tela e inseri-la dentro de outra 22
  23. 23. uiBinderHelloWorld.ui.xml<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"><ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"xmlns:g="urn:import:com.google.gwt.user.client.ui"> <ui:style> </ui:style> <g:HTMLPanel> <g:FlowPanel> <g:TextBox ui:field="txtBoxEntrada"/> <g:Button ui:field="buttonOk" text="Ok"/> </g:FlowPanel> <g:Label ui:field="labelHello"/> </g:HTMLPanel></ui:UiBinder> 23
  24. 24. uiBinderHelloWorldView.javapublic class HelloWorldView extends Composite { @UiField protected TextBox txtBoxEntrada; @UiField protected Button buttonOk; @UiField protected Label labelHello; private static PainelControlesUiBinder uiBinder =GWT.create(PainelControlesUiBinder.class); interface PainelControlesUiBinder extends UiBinder<Widget,HelloWorldView> { } public HelloWorldView() { initWidget(uiBinder.createAndBindUi(this)); } @UiHandler("buttonOk") public void onButtonOkClick(ClickEvent event) { ... }} 24
  25. 25. uiBinder 25
  26. 26. Model-View-Presenter Padrão de arquitetura de UI Criado para aumentar a testabilidade – No padrão MVC a View trabalha diretamente com o Modelo, podendo possuir lógica de negócio ou guardar o estado atual da execução. Isso torna difícil o teste de unidade, pois normalmente as telas só conseguem ser testadas com emulação de execução em testes de integração. 26
  27. 27. Model-View-Presenter Separa a lógica e a manutenção de estado da View – View apenas repassa para o controle, que nesse caso é chamado de Presenter, os eventos gerados pelo usuário, – Presenter possui toda a lógica e o estado da apresentação, sendo ele o responsável, inclusive, por atualizar os dados dos widgets da View. • Mesmo podendo existir lógica de exibição na View, os testes de unidade podem ser realizados apenas no Presenter, pois o risco de problemas de negócio na View é baixo. 27
  28. 28. Model-View-Presenter Foi subdividido em 2011 por Martin Fowler – Passive-View • View completamente passiva, não conhece as classes do modelo, se limita a repassar as modificações do usuário ao presenter e esperar que ele diga o que ela deve exibir. – Supervising Controller • View pode fazer data binding simples com o modelo, de forma a facilitar a implementação. Apesar dela poder editar o modelo, a edição é tão simples que o risco de não testá-la com testes de unidade continua mínimo 28
  29. 29. Model-View-PresenterPassive View Supervising ControllerView: View:@UiHandler("buttonOk") @UiHandler("buttonOk")public void onButtonOkClick(ClickEvent event) { public void onButtonOkClick(ClickEvent event) { presenter.onEntradaModificada hello.setQuem(txtBoxEntrada.getText()); (txtBoxEntrada.getText()); presenter.onHelloEditado(hello);} }public void setEntrada(String texto) { public void setEntrada(String texto) { txtBoxEntrada.setText(texto); txtBoxEntrada.setText(texto);} }public void setSaida(String texto) { public void setHello(Hello hello) { labelSaida.setText(texto); this.hello = hello;} labelSaida.setText(hello.getValor()); }Presenter:@Override Presenter:public void onHelloEditado(String texto) { @Override Hello hello = new Hello(texto); public void onHelloEditado(Hello hello) { if (isValido(hello)) { if (isValido(hello)) { this.hello = hello; this.hello = hello; view.setSaida(hello.getValor()); view.setHello(new Hello(hello)); } } view.setEntrada(""); view.setEntrada("");} } 29
  30. 30. Model-View-Presenter Qual utilizar? – Depende • Se os dados exibidos da View e repassados para o presenter pelo método de evento forem poucos, usar Passive View garante que os testes de unidade tenham cobertura maior de lógica. • Se a entidade possuir muitos campos, o método de evento do Passive View pode ficar com uma assinatura muito grande, gerando a necessidade de algum TO. Portanto pode valer a pena utilizar a própria entidade, o que nos leva ao Supervising Controller 30
  31. 31. Model-View-Presenter Maneiras de implementar – View sem gets • Todas os valores são passados ao presenter como parâmetros do método do evento acionado. • Pode gerar mais código repetitivo • Garante que o desenvolvedor que fez o presenter não irá usar a view para guardar estado. – View com gets dos valores • Método do evento acionado não precisa de parâmetros. • O desenvolvedor do presenter pode utilizar a view inequivocadamente para guardar o estado atual, o que impossibilita o teste de unidade do presenter. – O que importa é que siga a ideia de separar a lógica e a manutenção de estado da view para os testes. 31
  32. 32. Model-View-Presenterpublic class HelloWorldView extends Composite { public interface Presenter { void onEntradaEditada(String entrada); } @UiField protected TextBox txtBoxEntrada; @UiField protected Button buttonOk; @UiField protected Label labelHello; private Presenter presenter; private static PainelControlesUiBinder uiBinder =GWT.create(PainelControlesUiBinder.class); interface PainelControlesUiBinder extends UiBinder<Widget, HelloWorldView> { } public HelloWorldView() { initWidget(uiBinder.createAndBindUi(this)); } 32
  33. 33. Model-View-Presenter public void setPresenter(Presenter presenter) { this.presenter = presenter; } @UiHandler("buttonOk") public void onButtonOkClick(ClickEvent event) { fireEntradaEditada(); } @UiHandler("txtBoxEntrada") public void onEnterPressionado(KeyDownEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { event.preventDefault(); fireEntradaEditada(); } } private void fireEntradaEditada() { presenter.onEntradaEditada(txtBoxEntrada.getText()); } public void setSaida(String texto) { labelHello.setText(texto); } public void setEntrada(String texto) { txtBoxEntrada.setText(texto); }} 33
  34. 34. Model-View-Presenterpublic class HelloWorldPresenter implements HelloWorldView.Presenter { private HelloWorldView view; public HelloWorldPresenter(HelloWorldView view) { this.view = view; view.setPresenter(this); view.setEntrada(""); view.setSaida("Hello World"); } @Override public void onEntradaEditada(String entrada) { view.setEntrada(""); if (!entrada.isEmpty()) { view.setSaida("Hello " + entrada); } }} 34
  35. 35. Model-View-Presenterpublic class HelloWorld implements EntryPoint { /** * Método executado ao carregar o módulo. */ @Override public void onModuleLoad() { HelloWorldView view = new HelloWorldView(); HelloWorldPresenter presenter = new HelloWorldPresenter(view); RootPanel.get().add(view); }} 35
  36. 36. Comunicação com servidor Assíncrona – Envia requisição ao servidor e espera resposta, mantendo interface respondendo a entradas do usuário, podendo inclusive enviar/enfileirar outras requisições. – Não garante que a ordem de chegada das respostas das requisições seja a mesma ordem das requisições. 36
  37. 37. Comunicação com servidor Funcionamento geral para chamadas assíncronas – Prepara-se o método que será chamado, passando os parâmetros que serão utilizados. – Um objeto callback é passado para receber a resposta da requisição quando ela é disparada. Esta resposta é recebida a partir de métodos do callback, que são: • onSuccess: nenhum erro ocorreu na requisição e ela retornou, tem como parâmetro o tipo de retorno da chamada executada. • onFailure: quando alguma falha ocorre na requisição. Tem como parâmetro um objeto que especifica o erro. 37
  38. 38. Comunicação com servidor 38
  39. 39. Comunicação com servidor Um ponto importante – Toda a lógica e estrutura inicial das telas já estão no lado cliente ao carregar o módulo, porém sem nenhum dado. – Se uma tela que fica visível depende de dados do servidor para sua inicialização ela deveria ser exibida desabilitada até que os dados necessários cheguem. 39
  40. 40. Comunicação com servidorInicialização do GWT exibindo tela que precisa de dados do servidor JSF 40
  41. 41. Comunicação com servidor Comparando com JSF 41
  42. 42. Comunicação com servidor Possibilidades – Remote Procedure Call (RPC) • É a mais simples e que será mostrada nesta apresentação. Um único método é chamado por vez. – RequestFactory • Uma chamada de procedimento remoto mais robusta, que dá um tratamento mais completo a entidades, produz DTOs automaticamente, permite que várias chamadas a procedimentos sejam unidos em uma única requisição. – JsonP • Chamada que obteém resposta Json with Padding. Por ser uma resposta javascript normalmente utiliza JSNI. • É a única forma de fazer requisições para outro domínio. 42
  43. 43. Comunicação com o servidor Criando um serviço de Remote Procedure Call – O RPC executa procedimentos definidos em classes chamadas de services. • No cliente deve-se definir a interface do service, que terá os métodos poderão ser chamados via RPC, esta interface deve estender a interface RemoteService. • No servidor é feita a implementação da interface definida no cliente, essa implementação deve estender a classe abstrata RemoteServiceServlet. Esta classe é também um servlet java. • Na aplicação web deve-se declarar a classe de implementação do service como um servlet no web.xml. 43
  44. 44. Comunicação com o servidorHelloService.javapackage com.massahud.helloworld.client.rpc;@RemoteServiceRelativePath("hello")public interface HelloService extends RemoteService{ public String hello(String quem);}HelloServiceImpl.javapackage com.massahud.helloworld.server.rpc;public class HelloServiceImpl extends RemoteServiceServlet implements HelloService { @Override public String dizHello(String quem) { return "Hello " + quem; }}web.xml<servlet> <servlet-name>hello</servlet-name> <servlet-class>com.massahud.helloworld.server.rpc.HelloServiceImpl</servlet-class></servlet><servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/HelloWorld/hello</url-pattern></servlet-mapping> 44
  45. 45. Comunicação com o servidor Chamando o serviço do RPC – O cliente precisa do callback como parâmetro dos métodos para chamá-los de forma assíncrona. • Uma nova interface deve ser criada no cliente, com o mesmo nome da interface do service mas adicionada do sufixo Async. • Cada método da interface do service existente deve ser duplicado na interface Async, porém com o parâmetro AsyncCallback<TipoDeRetornoDoMetodo> adicionado ao fim da lista de parâmetros. • Crie uma instância da interface através do GWT.Create() • Chame o método RPC passando como último parâmetro o callback assíncrono que será chamado no retorno. 45
  46. 46. Comunicação com o servidorHelloServiceAsync.javapackage com.massahud.helloworld.client.rpc;public interface HelloServiceAsync { void dizHello(String quem, AsyncCallback<String> callback);} 46
  47. 47. Comunicação com o servidorHelloWorldPresenter.javapublic class HelloWorldPresenter implements HelloWorldView.Presenter { private HelloServiceAsync service; private HelloWorldView view; public HelloWorldPresenter(HelloWorldView view) { this.view = view; view.setPresenter(this); view.setEntrada(""); view.setSaida("Hello World"); service = GWT.create(HelloService.class); } @Override public void onEntradaEditada(String entrada) { view.setEntrada(""); if (!entrada.isEmpty()) { service.dizHello(entrada, new AsyncCallback<String>() { @Override public void onSuccess(String result) { onHelloDito(result); } @Override public void onFailure(Throwable caught) { onFalhaAoDizerHello(caught); } }); } }} 47
  48. 48. Comunicação com o servidor Pontos a considerar – Tentar limitar o corpo dos callbacks a uma única chamada de evento do seu presenter • Facilita o teste do comportamento ao receber o retorno do servidor • Provê reuso, com a funcionalidade podendo ser chamado diretamente, não precisando ser executado um RPC. – Apesar do exemplo estar criando uma classe anônima interna, é interessante criar uma classe não anônima para o callback • Provê reuso • Permite testes do callback 48
  49. 49. Conclusão Maior escalabilidade: – Executa lógica no cliente. – Após carregar o módulo troca apenas dados com o servidor. – Não mantém no servidor o estado da apresentação. – Servidor passa a ser um provedor de serviços. Maior usabilidade – Interface responde ao usuário mesmo durante execução de ações no servidor. – Troca mais rápida de telas, pois elas já estão pré- carregadas 49
  50. 50. Conclusão Maiores facilidades (para RIA) – Manter código java é normalmente mais fácil que código javascript. – Permite testes de unidade do cliente em java, que executam muito mais rápido que em javascript. – Acesso a toda a gama de funcionalidades que um IDE java provê. Outro paradigma de comunicação – Pode ser uma barreira para quem está acostumado com comunicação síncrona. 50
  51. 51. Conclusão Funcionalidades importantes ou interessantes não vistas – Controle de histórico e fluxo de execução • Place • Activity – Eventos – RequestFactory – JsonP – Cell widgets – Editors – Bean Validation (JSR303) – JSNI – GWTTestCase – Layout Panels – Suporte HTML5 51
  52. 52. Perguntas 52

×