terça-feira, 1 de março de 2011

ZK 5.0.6

A nova versão do ZK já está disponível para download aqui.
Como toda versão nova do ZK há sempre introdução de novas funcionalidades. Entre esses recursos novos estão:
  1. Geração de conteúdo customizado para SEO(Search Engine Optimization) onde agora é possível gerar um conteúdo específico que pode ser usado pelos indexadores de busca e transparentes ao usuários.
  2. Efeitos customizados quando mostrar oun esconder um widget atrávez de uma maneira simples sem uso de JavaScript.
Voce pode encontrar mais novidades aqui.

Construção de interfaces

Neste artigo vou continuar a falar sobre alguns fundamentais do ZK, como é feita a construção dos componentes, de que forma é possível fazê-lo e como anexar os componentes a uma página e será abordado também o conceito de Desktop e Page.
Mas antes gostaria de pautar alguns conceitos importantes:
  1.  JSON(JavaScript Object Notation) - Um formato leve para intercâmbio de dados computacionais. Outro link.
  2. JSP(Java Server Pages) - Uma tecnologia similar ao ASP da Microsoft ou PHP utilizada para desenvolvimento de aplicações web baseada em Java. Outro link.
Esse artigo foi baseado nos textos do site do ZK:
http://books.zkoss.org/wiki/ZK_Essentials/Introduction_to_ZK/Component_Based_UI http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/UI_Composing/Component-based_UI

Visão Geral

Cada objeto de interface é representado como um componente (Component). Assim, compor componentes trata-se da montagem de componentes. Para alterar a interface basta modificar os estados e a relação dos componentes.

Por exemplo, como mostrado abaixo, declaramos um componente Window, permitindo borda(border = "normal") e definindo sua largura em 250 pixels. Foram adicionados 2 componentes Button à Window.


Os componentes são declarados usando ZUML, em um arquivo ZUL, os quais são analisados por um poderoso parser XML do ZK. Os componentes declarados são criados como POJO(Plain Old Java Objects) na JVM no servidor. Suponha que temos uma página ZUL que descreve uma árvore de componentes como o seguinte:


    <button label="Hello" />
    <button label="Good-bye" />


A página com base ZUL renderiza uma janela com dois botões, como mostrado na imagem abaixo:
A marcação em ZUL é equivalente a seguinte declaração POJO em Java:

Window win = new Window();
    win.setTitle("ZKBrasil");
    win.setBorder("normal");
    win.setWidth("250px");
         
Button helloBtn = new Button();
    helloBtn.setLabel("Hello");
    helloBtn.setParent(win);
         
Button byeBtn = new Button();
    byeBtn.setLabel("Good-bye");
    byeBtn.setParent(win);

Os componentes no servidor são depois traduzidos para instruções (em JSON) necessárias para a criação de widget(objetos JavaScript) e enviado então para o cliente.



Como você pode notar, há duas maneiras de declarar um componente, através de XML ou Java puro:
  1. XML
  2. Os componentes são declaradas em arquivos com a extensão ".zul". Uma página ZUL é interpretada dinamicamente no servidor, podemos imaginar como um JSP capacitado com recursos Ajax. Por exemplo, aqui nós criamos um novo arquivo ajax.zul, e vamos implementar um pequeno exemplo de que a entrada do usuário no Textbox é refletido no label abaixo instantaneamente quando o Textbox perde o foco:
        
        <textbox id="txtbx" onChange="lbl.value = txtbx.value"/>
        <label id="lbl"/>
        
    
    
    A marcação declarada acima renderiza o simples programa abaixo:
  3. Java
  4. Os componentes poderiam ser declarados totalmente em Java também:
    package org.zkoss.zkdemo;
     
    import org.zkoss.zk.ui.Page;
    import org.zkoss.zk.ui.GenericRichlet;
    import org.zkoss.zul.*;
     
    public class TestRichlet extends GenericRichlet {
        //Richlet//
        public void service(Page page) {
            
            final Window win = new Window("ZKBrasil", "normal", false);
            win.setWidth("250px");
     
            Vlayout vl = new Vlayout();
            vl.setParent(win);
            
            final Textbox txtbx = new Textbox();
            txtbx.setParent(vl);
            
            final Label lbl = new Label();
            lbl.setParent(vl);
            
            txtbx.addEventListener("onChange", new EventListener(){
               @Override
               public void onEvent(Event event) throws Exception {
                   lbl.setValue(txtbx.getValue());
               }
           });
            
     
            win.setPage(page);
        }
    }
    
    Mais informações sobre Richlets podem ser encontradas aqui.
Além disso, voce pode misturá-las se quiser.

Estruturação dos Componentes


Como uma estrutura de árvore, um componente tem no máximo um pai, enquanto ele pode ter vários filhos.
Alguns componentes aceitam apenas tipos específicos de componentes como filhos, como por exemplo, o componente Grid aceita apenas os componentes Columns, Rows e Foot.
Outros não permitem nenhum tipo de componente, como por exemplo, o componente Textobox.

Um componente sem nehum pai é chamado de componente raiz (root componente). Múltiplos componentes raízes são permitidos em cada página, embora não seja comum.

Note que, se voce estiver usando ZUML, há uma limitação imposta pelo próprio XML: Exatamente uma raiz no documento é permitida. Para especificar várias raízes, é necessário inserir os componentes utilizando tag zk como raiz a qual é uma tag especial que não cria componentes. Por exemplo:


     <!-- O primeiro componente raiz -->
    <div/> <!-- O segundo componente raiz -->


Componentes Filhos


A maioria das coleções retornado por um componente, como Component.getChildren(), são de componentes "vivos", ou seja, existe algum componente adicionado na página. Significa que voce pode adicionar um componente, remover um componente ou remover todos. Por exemplo, para retirar todas os filhos, voce pode fazê-lo através da seguinte declaração:

comp.getChildren().clear();

A qual é equivalente a:

for (Iterator it = comp.getChildren().iterator(); it.hasNext();) {
    it.next();
    it.remove();

No entanto, isso também significa que o seguinte código não irá funcionar, pois a exceção ConcurrentModificationExceptionserá lançada.

for (Iterator it = comp.getChildren().iterator(); it.hasNext();)
    ((Component)it.next()).detach();

Ordenação


Um exemplo menos sutil: ordenação de componentes filhos. A seguinte declaração falha porque a lista contém todos os componentes "vivos" e um componente será retirado quando nós movermos ele para outro local.

Collections.sort(comp.getChildren());

Mais precisamente, um componente tem no máximo um pai e ele tem apenas um ponto na lista dos filhos. Isso significa que a lista é na verdade um conjunto (nenhum elemento duplicado é permitido). Por outro lado, Collections.sort() não consegue tratar um conjunto corretamente. Assim, temos que copiar a lista para outra lista ou vetor, e ordená-la. Components.sort(List, Comparator) é apenas uma maneira simples de reduzir o trabalho.

Desktop, Página e Componente


Imagine que os componentes são atores em um jogo, então a página é a fase onde os componentes desempenham os seus papéis. Uma página (Page) é um suporte de espaço em uma janela do navegador, onde os componentes ZK podem ser anexados e desanexados. A página não é um componente, não implementa a interface Component, mas é uma coleção de componentes e apenas os componentes ligados a uma página estão disponíveis no cliente. Uma página é criada automaticamente quando usuário requisita um recurso como uma página ZUL.

Um desktop (Desktop) é uma coleção de páginas. Ela representa a janela do navegador (ou um tab ou um frame do navegador). Você pode imaginar que um desktop representa uma requisição HTTP independente.


Um desktop é também o escopo lógico que uma aplicação pode acessar em uma requisição. Cada vez que uma requisição é enviada a partir do cliente, ela é associado ao desktop a que ele pertence. O pedido é passado para DesktopCtrl.service(AuRequest, boolean) e, em seguida encaminhado para ComponentCtrl.service(AuRequest, boolean). Significa também que a aplicação não pode acessar componentes em vários desktops ao mesmo tempo.

Um desktop e uma página são criados automaticamente quando o ZK Loader carrega uma página ZUML ou chama um richlet(Richlet.service(Page)). A segunda página é criada quando o componente Include inclui outra página com o modo defer. Por exemplo, duas páginas serão criadas se o seguinte for visitado.

<!-- Página principal -->

  <include src="another.zul" mode="defer"/> <!-- Cria outra página -->


Repare que se o modo não for especificado (ou seja, o modo instant), o incluide não irá criar uma nova página. Em vez disso, ele anexará todos os componentes criados por another.zul como seus componentes filhos próprios.


  <include src="another.zul"/> <!-- default: mode instant -->


É equivalente a seguinte declaração (exceto div não é um proprietário do espaço, veja abaixo)


  <div>
    <zscript>
      execution.createComponents("another.zul", self, null);
    </zscript>
  </div>


Anexar um componente a uma página


Um componente está disponível no cliente somente se ele está anexado a uma página. Por exemplo, a janela criada a seguir não estará disponível no cliente.

Window win = new Window();
win.appendChild(new Label("foo"));

Um componente é um objeto POJO. Se você não tem qualquer referência a ele, ele vai ser reciclado quando a JVM iniciar o Garbage Collection.

Há duas maneiras de anexar um componente de uma página:
  1. Acrescentá-o como um filho de outro componente que já está conectado a uma página (Component.appendChild(Componente), Component.insertBefore(Componente, Componente), ou Component.setParent(Componente)).
  2. Chamar Component.setPage(Page) para anexá-lo a uma página diretamente. É também a maneira de fazer um componente se tornar um componente raiz.

Uma vez que um componente pode ter no máximo um pai e ser anexado no máximo a uma página, é desanexado automaticamente a partir do pai ou da página anterior quando ele é anexado a outro componente ou página. Por exemplo, b será um filho de win2 e win1 não terá nenhum filho no final.

Window win1 = new Window;
Button b = new Button();
win1.appendChild(b);
win2.appendChild(b); //implica desanexar b de win1

Desanexar um componente a uma página


Para desanexar da página, você poderia chamar comp.setParent(null), se não for um componente raiz, ou comp.setPage(null), se for um componente raiz. Component.detach() é um atalho para desanexar um componente sem saber se ele é um componente raiz.

Invalidar um componente


Quando um componente é anexado a uma página, o componente e todos os seus descendentes serão renderizados. Por outro lado, quando um estado de um componente anexado é alterado, apenas o estado alterado é enviado ao cliente para atualização (para melhor desempenho). Embora seja raro, você poderia chamar Component.invalidate() para forçar o componente e seus descendentes a serem renderizados novamente(O ZK Update Engine irá enfileirar os comandos update e Invalidate, e otimizá-los antes de enviar de volta ao cliente para uma melhor performace).

Existem apenas algumas razões para invalidar um componente:

  1. Se você estiver adicionando vários componentes filhos, pelo menos mais de 20, o desempenho será melhor se você invalidar o componente pai. Embora o resultado da resposta Ajax possa ser grande, o navegador é mais eficiente em substituir uma árvore DOM do que a adicionar elementos DOM.
  2. Se um componente tem um bug que uma atualização não atualiza a árvore DOM corretamente, você pode invalidar o seu componente pai, que geralmente resolve o problema (Qualquer tipo de bug pode ser relatado no forum da comunidade. Se confirmado, ele será resolvido na próxima versão).

Não guarde referências de componentes adicionados a uma Página em campos estáticos


Como descrito acima, um desktop é um escopo lógico que a aplicação pode acessar ao atender a uma requisição. Em outras palavras, a aplicação não pode desanexar um componente de um desktop para outro desktop. Isso normalmente acontece quando é referenciado um componente acidentalmente.

Por exemplo, o código a seguir lançará exceção se ele for carregado várias vezes:

 <!--  Instancia e executa foo.Foo -->

e foo.Foo é definido a seguir:

package foo;
import org.zkoss.zk.ui.*;
import org.zkoss.zul.*;
 
public class Foo implements org.zkoss.zk.ui.util.Composer {
   private static Window main; //Errado! Não guarde em um campo estático
   public void doAfterCompose(Component comp) {
       if (main == null)
           main = new Window();
       comp.appendChild(main);
   }
}

A exceção é parecida com essa:

org.zkoss.zk.ui.UiException: The parent and child must be in the same desktop: 
    org.zkoss.zk.ui.AbstractComponent.checkParentChild(AbstractComponent.java:1057)
    org.zkoss.zk.ui.AbstractComponent.insertBefore(AbstractComponent.java:1074)
    org.zkoss.zul.Window.insertBefore(Window.java:833)
    org.zkoss.zk.ui.AbstractComponent.appendChild(AbstractComponent.java:1232)
    foo.Foo.doAfterCompose(Foo.java:10)

Clonando Componentes


Todos os componentes são clonáveis (java.lang.Cloneable). É simples replicar componentes invocando Component.clone().

main.appendChild(listbox.clone());

Note:
  • É um clone de profundidade. Ou seja, todos componentes filhos e descendentes são clonados, também.
  • O componente retornado por Component.clone() não pertence a nenhuma página e ele não tem um pai também. Você deve anexá-lo manualmente, se necessário.

  • O ID será preservado, se houver. Assim, você não pode anexar o componente retornado para o mesmo espaço de ID, sem modificar o ID, se houver.

Da mesma forma, todos os componentes são serializáveis (java.io.Serializable). Como a clonagem, todos os filhos e descendentes são serializados. Se você serializa um componente e, em seguida, deserializá-lo de volta, o resultado é o mesmo que chamar Component.clone()(Mas a performace de executar Component.clone() é muito maior).

sábado, 4 de dezembro de 2010

Arquitetura do ZK

Neste artigo, irei abordar sobre a arquitetura do ZK. Mas antes disso, gostaria de falar sobre alguns conceitos importantes:
  1.  POJO(Plain Old Java Objects) - São objetos Java que não dependem da herança de interfaces ou classes de frameworks externos. Outro link.
  2. JavaScript - Linguagem de script interpretada pelo borwser.
  3. DOM(Document Object Model) - Convenção criada peloa w3school, independente de plataforma e linguagem, para acessarem e manipularem elementos XML, HTML e XHTML através de objetos.
  4. AJAX(Asynchronous Javascript And XML) - Significa o uso de tecnologias como JavaScript e XML, providenciadas pelo navegador, para tornar as páginas Web mais interativas com os usuários, através de requisições assícronas.
Esse artigo foi baseado no texto do site do ZK: http://books.zkoss.org/wiki/ZK_Developer's_Reference/Architecture_Overview

Será abordado 2 perspectivas sobre o ZK: Aplicação e Componente. A primeira mostra uma visão a nível de aplicação, a segunda mostra uma visão a nível de componente.

Visão geral da arquitetura:

Visão do desenvolvedor da aplicação:

O ZK possui uma arquitetura server-centric(centrada no servidor), isso quer dizer que a aplicação ZK roda no servidor. Ela pode acessar os recursos backend, montar a interface com os componentes, ouvir a atividades do usuário, e então manipular componentes para atualizar a interface. Tudo é feito no lado do servidor. A sincronização dos estados dos componetes entre o browser e o servidor é feito automaticamente pelo ZK, e transparente pela aplicação.

Quando executada no servidor, a aplicação pode acessar a stack completa da tecnologia Java. Atividades do usuário são, incluindo AJAX e Server Push, abstraidas para objetos de eventos. A interface são compostas por componentes tipos POJO. Essa é a abordagem mais produtiva para desenvolver uma moderna aplicação web.

A partir do ZK 5, foi introduzido uma mundaça na arquitetura chamada de Server+Client Fusion. Assim a sua aplicação não para no servidor. É possível melhorar a interatividade de sua aplicação através da adição opicional de funcionalidades do lado do cliente(client-side), como o tratamento de evento pelo lado do cliente, efeitos visuais customizados, e até mesmo compor interfaces sem a codificação no lado do servidor. A versão 5 permite a fusão perfeita do servidor e cliente.Assim, voce pode ter o melhor dos 2 mundos: produtividade e flexibilidade.
Um artigo serã escrito mais tarde abordando o Server+Client Fusion.

Visão do desenvolvedor de componente:

Cada objeto de interface no ZK consiste de um componente e um widget. Um componente é um objeto Java sendo executando no servidor o qual representa um objeto de interface o qual pode ser manipulado por uma aplicação Java. Um componente possui todos os comportamentes de objeto de interface exceto a parte visual. Um widget é um objeto Javascript sendo executado no cliente. Esse objeto representa o objeto de interface o qual interage com o usuário. Por isso, um widget geralmente poussi uma aparencia visual, e manipula eventos ocorridos no cliente.

O relacionamento entre um componete e um widget é um um-pra-um. Mas, se um componente não é anexado a uma página, ele não possuirá um widgt correspondente no cliente. Por outro lado, é permitada a aplicação instanciar widgets no cliente diretamente sem o componente correspondente.

É função do componente sincronizar os estados e distribuir a carga. O ZK Client Engine and update Engine trabalham juntos para propocionar um elegante e robusto canal para simplificar a implementação.

Por exemplo, assuma que voce queira implementar um componente que permite o usuário clicar sobre um elemento DOM para mostrar alguma informação detalhada de um componente. Existe pelo menos 2 abordagens para essa implementação. Primeiro, nós podemos carregar a informação detalhada para o cliente quando o widget é instanciado, e então mostrar o detalhe via código client-side. Alternativamente, nós podemos preferir não carregar a informação do detalhe logo de começo, e então enviar uma requisição de volta ao servidor para preencher o detalhe quando o usuário clicar.

Obviamente, a primeira abordagem requer mais largura de banda para a requisição inicial mas possui uma resposta rápida quando o usuário clicar. Porém, isso é geralmente transparente para o desenvolvedor da apicação, e a implementação do componente pode ser aperfeiçoada conforme a fase de desenvolvimento da aplicação.

Fluxo de Execução do carregamento de uma página:

  1. Quando um usuário digita uma URL ou clica num link no browser, uma requisição é enviada para o servidor web. Se a URL requisitada corresponde ao padrão de URL configurado do ZK(isso pode ser customizado), o ZK loader é então invocado para servir a essa requisiçáo.
  2. O ZK loader carrega a página especificada e interpreta-a para criar os componentes especificos de acordo com a página.
  3. Depois de interpretar a página toda, o ZK loader renderiza o resultado em uma página HTML. A página HTML é então enviada de volta ao browser acompanhada do ZK Client Engine.
  4. O ZK Client Engine renderiza os widgets em elementos DOM e insere os elementos DOM na árvore DOM do borwser para torná-los visíveis ao usuário.
  5. Logo, o ZK Client Engine fica no browser para servir as requisições feitas pelo usuário. Se ele vai para outra página, o fluxo de execução começa novamente. Se ele vai enviar uma requisição AJAX de volta, outro fluxo de execução começa conforme descito no próximo item.
O ZK Client Engine é escrito em JavaScript. Browsers irão fazer cache do Z Client Engine, logo ele é geralmente enviado apenas uma vez no primeiro acesso.

Fluxo de Execução ao servir uma requisição AJAX:

  1. O fluxo de execução é iniciado pelo widget ou pela aplicação; geralmente causado por uma atividade do usuário(ou requisitos da aplicação). Isso é geralmente feito por enviar uma evento do lado do cliente(Event) para um widget (Widget.fire(Event, int)).
  2. O evento é então propagado ao pai do widget, ao pai do pai, e finalmente ao ZK Client Engine(Um widget pode escolher parar essa propagação através de Event.stop(Map)).
  3. Se necessário, o ZK Client Engine envia uma requisição AJAX para o ZK Update engine no servidor( Do ponto de vista do servidor, uma requisição AJAX é apenas outra requisição HTTP).
  4. Ao receber uma requisição AJAX, o ZK Update Engine invoca o ComponentCtrl.service(AuRequest, boolean) para o tratamento da requisição.
  5. A manipulação é com o componente. Mas, geralmente é feita a atualização dos estados, se necessário, e então notifica a aplicação enviando eventos( Events.postEvent(Event)).
  6. Se algum evento for enviado, o ZK Update Engine processará eles um-por-um invocando os events listeners, se houver.
  7. O event listener, provido por uma aplicação, pode escolher atualizar os recursos de backend, atualizar os componentes ou postar outros eventos.
  8. Finalmente, o ZK Update Engine recolhe todas as atualizações de componentes, incluindo mudanças nos estados, attachment e detachment. Otimizá-os, e depois envia de volta uma coleção de comandos de volta ao cliente.
  9. O ZK Client Engine avalia cada um desses comandos para atualizar o widget de acordo com cada um. E, os widgets atualizarão a árvore DOM do browser para torná-los disponíveis para o usuário.

Quando enviar uma requisição AJAX:

Quando o ZK Client Engine recebe um evento propagado pelo lado do cliente(Event), ele decidirá se e quando enviar o mesmo de volta ao servidor para processamento adicional.
  1. Se existe um event listener não adiável(deferrable) registrado no servidor, o pedido é enviado imediatamente. Um event listener não adiável é um event listener (EventListener) que não implementa Deferrable. Por padrão, (sem implementar Deferrable) todo o evento é enviado imediatamente ao servidor quando ele é acionado no cliente.
  2. Se existe um event listener adiável registrado no servidor, a requisição será colocado numa fila no cliente e será enviada quando outro evento for acionado e um event listener não adiável for registrado por ele. Para tornar um listener adiável, voce deve implementar Deferrable e retornar true para isDeferrable().
  3. Se o widget declarar o evento o evento como importante(ComponentCtrl.CE_IMPORTANT), o evento será adicionado na fila para ser enviado depois também.
  4. Se não for nenhum dos casos acima ou o widget não tem nenhum componente corresponde no servidor, o evento é cancelado.
Os eventos adiáveis são usados para melhorar o desempenho, minimizando o tráfego entre o cliente e o servidor. É comumente usado por events listener que mantém estados da aplicação, ao invés de gerar respostas visuais.

Bem galera é essa é uma breve visão da arquitetura do ZK.. No próximo artigo irei falar de mais alguns conceitos importantes.

sexta-feira, 5 de novembro de 2010

Primeiros Passos

Com o nosso ambiente configurado no artigo anterior, vamos adicionar algums funcionalidades a nossa tela e ver como o ZK Studio funciona.

O Zk Studio permite auto-complete dentro de arquivos .zul e possui alguns recursos interessantes como drag-and-drop de componentes para os arquivos ZUL através do ZUL Palette, visualização em árvore dos componentes dentro do Outline, manipular as propriedades de um componente selecionado dentro do Properties, renderização do arquivo zul dentro do ZUL Visual Editor e uma vizualização das versóes instaladas e exemplos de códigos através do Sample Codes.

Sabendo um pouco melhor como o ZK Studio é estruturado, vamos começar a modificar o nosso exemplo.
Com o Eclipse aberto, vamos mudar a perspectiva para a do ZK. No canto superior direto, clique no botão "Open Perspective" e escolha a do ZK.

Feito isso sua tela deve estar parecida com essa:
Feito isso vamos abrir o arquivo index.zul e editar alguns coisas:

<?page title="Hello World"?>
<window title="Minha Primeira Janela" border="normal" width="200px">
<label value="Hello World!" />
</window>

Troquei o atributo title da pagina e da window, e o value de label.
Rode o servidor, e a tela gerada deve ficar assim:

Em ZK, voce escreve em ZUML(ZK User Interface Markup Language), linguagem essa baseada em XML.
Cada atributo alterado, altera cada propriedade de um componente.
Algumas propriedades do componente Window:

Propriedade Função Valor
title Define o título da janela qualquer texto
border Define o estilo de borda da janela normal ou none (padrão)
height Define a altura da janela numero de pixels (Ex: 100px)
width Define o comprimento da janela numero de pixels (Ex: 100px)
closable Define se ou não a janela pode ser fechada true ou false
sizeable Define se ou não a janela pode ser redimensionada true ou false
Vamos alterar a nossa janela pra ficar com um comprimento de 100px, ser redimensionável e fechada. Com as mudanças feitas, basta voce recarregar a pagina. Deve ficar assim:
Tente redimensionsar e/ou fechar a janela.

Agora vamos adicionar uma botão e um evento, ficando assim:

<?page title="Hello World"?>
<window title="Minha Primeira Janela" border="normal" closable="true"
sizable="true" width="200px">
<label value="Hello World!" />
<button label="sayHello" onClick='alert("Hello World!")' />
</window>

Ficando assim:

O evento onClick é acionado quando o botão é clicado, gerando, nesse caso, um alert com o valor "Hello World!". A função alert() é um função global que gera um alerta, similar a função alert() presente no Javascript. O ZK possui alguns objetos e funções globais, mas isso será abordado em outro artigo.
Mas essa não é a única maneira de descrever como o evento vai ser tratado. Eis uma outra maneira:

<?page title="Hello World"?>
<window title="Minha Primeira Janela" border="normal" closable="true"
sizable="true" width="200px">
<label value="Hello World!" />
<button label="sayHello" onClick="sayHello()" />
<zscript>
void sayHello() {
Messagebox.show("Hello World!");
}
</zscript>
</window>

Dessa vez eu escrevo o código Java dentro de um zscript. Esse tipo de tag significa que voce pode escrever scripts, mas em vez de serem processador no cliente serão processados no servidor. O zscript aceita mais de um tipo linguagens, basta voce dizer qual no atribute language, sendo Java o padrão.
Podemos observar que dessa vez eu utilizei uma outra maneira de criar um alert através do objeto Messagebox, similar ao JOptionPane, podendo passar vários parametros nas funções caso eu queira uma mensagem tipo alerta ou error.
Agora, se quisessemos, por exemplo trocar uma tributo o nome do nosso label?
Podemos fazer isso acessando o componente pelo id. Para cada componente é gerado um id automaticamentetem, mas eu posso definiar uma, e nesse caso foi o que eu fiz :

<?page title="Hello World"?>
<window title="Minha Primeira Janela" border="normal" closable="true"
sizable="true" width="200px">
<label id="mylabel" value="Hello World!" />
<button label="sayHello" onClick="change()" />
<zscript>
void change() {
mylabel.value = "ZKBrasl";
}
</zscript>
</window>


Depois de o botão ter sido clicado:
O label foi alterado, sem muita dificuldade, com uma chamada de evento paracida com Java mas que por trás roda AJAX. :)
Veja que estamos alterando o atributo value do componente, mas poderiamos ter feito isso através do método setValue. Isso pode ser feito porque cada componente ZK é formado por uma parte visual e uma parte Java. Isso será abordado melhor mais em outro artigo.

O ZK tem suporte a EL (Express Language) através da sintaxe ${exp}. Vamos agora, definiar que o valor de um botão será o mesmo de um outro botão:

<?page title="Hello World"?>
<window title="Minha Primeira Janela" border="normal" closable="true"
sizable="true" width="200px">
<button id="button1" label value="sayHello" />
<button id="button2" label="${button1.label}" />
</window>

EL Será abordado melhor em outro artigo.

Até agora escrevemos os nosso códigos de tratamento de evento dentro de um arquivo .zul, mas e se quisesemos escrever em outro lugar?
Claro que podemos! O ZK tras um bom suporte ao padrão MVC, nesse caso voce deve implementar uma classe java para tratar os eventos. A classe deve estender GenericComposer.


<?page title="Hello World"?>
<window title="Minha Janela" border="normal" width="200px"
apply="view.MyComposer">
<button label="say Hello" forward="onSayHello" />
</window>

view.MyComposer

public class MyComposer extends GenericComposer {
public void onSayHello(Event evt) {
evt.getTarget().appendChild(new Label("Hello"));
}
}

Depois de o botão ter sido clicado:



Vimos um pouco mais como o ZK funciona, e como o ZK trata eventos de uma maneira simples e rápida.
Vimos alguns componentes simples, mas exitem vários outros.

Voce pode consultar uma demo dos componentes aqui:  http://www.zkoss.org/zkdemo/
No próximo artigo veremos um pouco mais de como o ZK funciona por dentro.


ATUALIZAÇÃO - 04/12/2010
Uma outra maneira mais simples na hora de tratar eventos e que eu costumo usar é fazer com que a minha classe onde eu trato os meus eventos estenda de GenericForwardComposer. Assim o nosso exemplo fica assim:


 

view.MyComposer

public class MyComposer extends GenericForwardComposer {

 Window win;
 
 public void onClick$btn(Event evt) {
  win.appendChild(new Label("Hello"));
 }
}


Dessa forma retiramos o atributo forward de button, colocamos um id nele e em window também.
Na classe, declaramos uma variável com nome similar ao id de window e do tipo Window. Dessa forma forma o ZK vai saber que aquela várial está se ligando a Window na parte de visão cujo id bate com o nome da variável e tipo também. O nome do método agora segue uma convenção de nomes para tratamentos de eventos: "event_name$component_id". Dessa forma quando o evento for disparada e redirecionado para essa classe, ele vai comparar o tipo de evento e depois o id do componente o qual  disparou o evento. Dessa forma o código fica mais limpo e máis fácil de manter.

Em geral os exemplos postados no blog irá utilizar uma abordagem mais parecida com essa.

terça-feira, 2 de novembro de 2010

Configurando o ZK

Neste artigo irei abordar a configuração do Eclipse e o ZK Studio, plugin pro Eclipse, para trabalhar com o ZK.

Ferramentas necessárias:
  1. JDK 6
  2. Eclipse Helios Java EE
  3. Tomcat 7
  4. Algum browser, recomendo o Firefox.
  5. ZK 5.0.5, versão da data deste artigo.
  6. ZK Studio
Após a instalação do JDK, baixe o Eclipse, e descompacte no local que preferir. 
No meu caso foi escolhido o caminho C:\Java\eclipse, com worspace em C:\Java\workspace.
Feito isso, baixe o tomcat 7 e descompacte para C:\Java\tomcat.
Abra o Eclipse. No menu navegue para Window -> Show View -> Other... , 
ou no canto inferior esquerdo clique no botão "Show View as fast view", e procure por Servers.
Com a janela aberta, clique com o botão direito dentro da janela e vá para New -> Server.
Nessa janela escolha o Tomcat v7.0 Server e clique next.

Na Janela seguinte, procure pelo diretório do Tomcat 7 e clique em finish.
Feito isso vamos baixar o ZK Studio. navegue até Help -> Install New Software....
Nessa Janela voce clicar em Add..., para adicionar uma nova url de busca de plugins para o Eclipse.
Em Name, coloque o nome de ZK Studio e Location o url para download descrita no site.
Feito isso, o Eclipse irá buscar o plugin. Escolha o plugin ZK Studio e instale.

Antes de criar um projeto vá em Window -> Preferences, escolha o item ZK e depois ZK Packages. Voce notará que a versão utilizada é a 3.6.3. Baixe a última versão do ZK, na janela anterior escolha clique em Add File/ Directory..., depois em File Import. Escolha o local onde está o arquivo .zip da versão do ZK e depois em finish. Marque a opção da versão mais nova. O ZK Studio não atualiza a versão do ZK sozinho, então a cada nova versão que voce deseja instalar voce deve realizar esse procedimento, É permitido que voce tenha projetos ZK com versão diferentes basta voce configurar cada projeto separadamente. A cada novo projeto, o Eclipse irá gerar com a versão escolhida aqui
Clique em apply e depois finish.
Voce pode notar que no Project Explorer existe as 2 versões das libs:
Feito isso, vamos criar um novo projeto ZK. Vá em File -> New -> Other... e escolha ZK Project.
O nome do nosso projeto vai ser HelloWorld:
Note que ele mostra a versão do ZK utilizada e o servidor a ser utilizado, podendo ser configurado antes de cada projeto.
Lembre-se de selecionar a versão 2.5 do Dynamic web module, e clique em Finish.
Feito isso vamos analisar melhor o projeto gerado:
Em Java Resources ficam as classes Java, arquivos XML, arquivos texto, etc.
Dentro de WebContent fica os arquivos que irão serão responáveis pela vista como os arquivos ZUL. No projeto gerado temos 2 : index e o timeout.
Quando um url é enviada para o servidor, o servidor irá processar e devolver o arquivo index por padrão, mas isso pode ser configurado para enviar outro arquivo. Como estamos trabalhando com uma aplicação AJAX, existe um tempo de resposta para a pagina. Quando tenta-se acessar um componente e é gerado um evento mas o tempo de resposta acabou, o servidor processa e devolve a pagina timeout com uma resposta, também podemos configurar a mensagem de timeout e o tempo de resposta.
Nessa pasta podemos ter outras pastas, contendo outros arquivos .zul, .html, .css, .js, imagens, entre outras coisas.
Dentro da pasta WEB-INF temos todas as libs usadas no projeto e os arquivos web.xml e zk.xml, usados para configurar nossa aplicação. Se precisarmos adicionar alguma lib extra, basta adicionar na pasta lib.

Agora vamos iniciar a aplicação. COm o botão direito na projeto, seleciona Run As -> Run on Server.
Irá aparecer uma tela pra voce escolher o servidor o qual voce deseja rodar a apicação. No nosso caso o tomcat já está selecionado, então basta clicar em Finish. Voce pode marcar uma opção que permite que ele sempre rode dentro do servidor selecionado, se preferir.
Feito isso temos, nossa primeira aplicação funcioando:

ATUALIZAÇÃO - 03/12/2010
Na imagem de criação de projeto ZK aparece um warning dizendo que precisa do JDK instalado.
Para resolver isso basta ir em Window->Preferences e depois navegue para Java -> Installed JREs.
Escolha a versão da jre instalada e clique em edit. Em JRE home basta colocar o caminho do JDK, no meu caso está em C:\Java\jdk1.6.0_20. Se quiser renomear o nome de jre para jdk fique a vontade.
Feito isso não vai mais aparacer aquele warning.



segunda-feira, 1 de novembro de 2010

O que é o ZK?

Inicio a minha série de postagens falando mais sobre o que o ZK:

O ZK é um framework orientado a eventos para desenvolvimento web baseado em AJAX de código aberto. Permitindo o desenvolvimento de interfaces ricas para aplicações web com pouca programação e um custo de desenvolvimento reduzido, tal como as antigas aplicações desktop. 
O ZK utiliza uma linguagem de meta-definição baseada em XML (ZUML) para definir a interface do usuário traduzindo para código HTML quando a página é solicitada pelo cliente.
O ZK foi o primeiro projeto AJAX + mobile no SourceForge.net, acumulou 1.500.000 downloads, e foi referenciado por mais de 4.000 web sites desde o lançamento da primeira versão em 2005.


O ZK possui quase tudo feito de bandeja:
  • Diversos componentes prontos: Tabbox, grid, listbox, tree, menu, combobox, bandbox, datebox, chart, hbox, vbox, window, slider, paging, audio, image, timer, include, iframe, etc
  • Drag-and-drop suportado por todos componentes
  • Menu de Contexto e Tooltips customizaveis suportado por todos componentes
  • Ordenação Customizada de listbox, grid etc
  • Auto-preenchimento para combobox
  • “Load on demand” sem escrever nenhuma linha de código
  • “Live data” ou “Load on demand” para listbox
  • Todos componentes são clonáveis e serializáveis
  • Validação e formatação para componentes de entrada de dados, com suporte completo a uso de expressões regulares e $#,##0
  • 100% API Java para os componentes Google Maps, FCKeditor, DOJO e Timeline
  • Componente Tree com paginação
  • Server push, chamado de reverse-ajax, permite o servidor enviar dados para clientes ativos, ou seja, facilmente é capaz de se desenvolver sistema de CHAT.
  • Em adição, componentes TreeModel, Timebox e Flash
  • Modelo server-side e baseado em eventos
  • Mais de 20 eventos suportados; onChange, onChanging, onScroll, onSelect, on Show, onZIndex, etc
  • Todos os eventos são processados no servidor
  • Todos os eventos estão sincronizados. Não possui problema de “Racing Condition”
  • Scripting usando expressões EL. Inclui, mas não limitado, a Java, Javascript, Ruby, Groovy e Python
  • Mudanças noa interface do usuário sem necessidade de restarting da aplicação
  • Anotações que permite uma página acessar a base de dados sem escrever código Java
  • Macro componentes
  • Facilidade em encapsular componentes puramente clientes como componentes do ZK usando 100% a API Java
  • Dialogos Modais verdadeiramente server-side
  • Internacionalização
  • MVEL plug-in

Facilidade de utilização
Simplicidade é um dos valores de base do ZK. Outra facilidades que se encontra nesse framework, é a disponibilidade com que a sua equipa de desenvolvedores está disposta a ajudar.
A criação de novos/customizados componentes é bastante simples e a documentação é muito boa e bem detalhada.


Independência de plataforma
O ZK Mobile possui vários componentes já de bandeja: listbox, listitem, textbox, image, label, command, datebox, decimalbox, intbox, frame
O ZK suporta os seguintes browsers: Internet Explorer 6/7+, Firefox 1+, Safari 2+, Mozilla 1+, Opera 9+ and Camino 1+. Escreve uma vez e rode em todos os browsers sem problemas de compatibilidade.
Roda em qualquer web Server que suporta Servlet 2.3+ e JVM 1.4+



Licença
A licença padrão do ZK é LGPL. No entanto, existem licenças pagas os componentes mais avançados que segue o mesmo padrão do famoso MySQL.


Integração com outros frameoworks
Possui integração com outros frameworks, como Spring, Hibernate, JSP, JSF. ExtJs, Google Maps, FCKeditor, DOJO e Timeline.


Enfim, muitas coisas ficaram por analisar. 
Com muitos componentes já prontos, AJAX imbutido, integração com frameworks populares, suporte da comunidade e open-source, torna o ZK uma exelente escolha para o desenvolvimento de aplicações web.


    sábado, 18 de setembro de 2010

    Primeiro Post...

    Olá a todos!
    Assim estreio a minha participação no meu primeiro Blog! rs
    Esse blog tem como objeto falar sobre o framework RIA ZK, coisas relacionadas a Java e desenvolvimento de software.
    Espero abordar tanto o basico quanto o avançado na parte de desenvolvimento web com o ZK.

    That's all folkes!