09 maio 2007

Herança em Anotações Java

Brincando com o Hibernate Validator hoje, notei que seria uma ótima idéia ter herança de anotações em Java. Algo que atualmente não é permitido. Realmente, senti falta dessa funcionalidade.

Comecei escrevendo um POJO simples para configurar algumas validações de @Range, quando notei a repetição. Esta anotação recebe dois parametros min e max, ficando assim:
class User {
@Range(min=6, max=20)
private String password;
...
}

Mas, obviamente este é o mais simples dos simplérrimos exemplos onde quero demonstrar apenas o uso da anotação e porque herança seria algo útil. Em muitos outros atributos, inclusive de outras classes, gostaria de aplicar o mesmo @Range e atualmente a única solução é copiando/colando a definição.

E se eu pudesse fazer isso:
public @interface Range6to20 extends @Range(min=6, max=20) {}

Não seria ótimo? Bastaria um @Range6to20 nos atributos que quero, e tenho apenas um ponto para alterar o range, caso seja necessário futuramente. (Ok, o nome da classe iria ficar em desacordo com os valores, mas e daí? é um exemplo!... e também, o refactor do Eclipse renomeia as referencias... então... não é um problema).

Quem já viu as anotações do Struts 2 para o Validator? Ficam enormes não é? E se você pudesse estender e colocar separadamente a configuração numa anotação especializada, e de quebra ainda poder reutilizá-la em outros lugares? :D Seria ótimo, não?

Pesquisei na web algo sobre herança de anotações, mas o máximo que encontrei foi alguém comentando que também gostaria de ter, e que soube que o assunto foi discutido pelo Expert Group da respectiva JSR, só não soube dizer porque essa funcionalidade não foi incorporada. Talvez alguém saiba?

O que vocês acham? :)

[]'s!!
miojo

08 maio 2007

Wicket: AJAXiando a Paginação

No penúltimo post, mostrei como implementar paginação de listas com o framework Wicket. Agora, visando maior produtividade e usabilidade na interface, apresento-lhes o que é preciso para implementar a mesma paginação ajaxiada.

O processo é o mesmo, já que o framework é component-based. As alterações no HTML são mínimas e mesmo em Java, o que será preciso modificar é qual componente instanciar para tratar a ListView. Mas por se tratar de uma implementação Ajax, algumas considerações e explicações devem ser feitas antes.
  • Ao implementar algo em Ajax, as vezes é preciso de uma área (div) para ser atualizada pelas requisições assíncronas com novo código HTML produzido dinâmicamente no servidor.
  • No caso da ListView, é importante que a tabela fique dentro de uma área como esta.
  • Em Wicket, é possível referenciar uma área qualquer div através do componente WebMarkupContainer.
Uma das enormes vantagens de utilizar o framework Wicket, é poder desenvolver diversas funcionalidades sem escrever uma linha de Javascript qualquer. Seu suporte a Ajax está muito estável para funcionalidades básicas, e ainda existe o projeto Wicket Extensions que provê muitos outros componentes 100% plugáveis a qualquer aplicação Wicket. Cada componente expõe no HTML de alguma forma, o Javascript necessário para que o mesmo funcione, como os de Ajax por exemplo. Em outro post, mostrarei como implementar componentes reutilizáveis (e aí sim, teremos que escrever Javascript se for o caso).

Seguindo o assunto do post, vamos ao que interessa: ajaxiar uma paginação. Abaixo, está o código da tela utilizada na explicação anterior:

Pessoas.html
<table>
<tr>
<td>nome</td>
<td>idade</td>
</tr>
<tr wicket:id="lista">
<td><span wicket:id="nome">foo</span></td>
<td><span wicket:id="idade">12</span></td>
</tr>
<tr>
<td colspan="2">
<span wicket:id="navegacao">Aqui vai a barra de navegacao</span>
</td>
</tr>
</table>

A única alteração que devemos fazer, é colocar esta tabela dentro de uma área atualizável por requisição Ajax: um div. Ou seja, ficará assim:

<div wicket:id="ajaxTable">
<table>
<tr>
...
</tr>
</table>
</div>


Feito isto, é preciso que o componente ajaxTable seja reconhecido pelo Wicket na classe Pessoas. E é agora que utilizaremos a classe WebMarkupContainer:

Pessoas.java
public class Pessoas extends WebPage {
public Pessoas() {
List listaPessoas; /* obtem de algum lugar (Spring talvez) */
PageableListView view = new PageableListView("lista", listaPessoas) {
protected void populateItem(ListItem item) {
Pessoa p = (Pessoa) item.getModelObject();
item.add(new Label("nome", p.getNome());
item.add(new Label("idade", p.getIdade());
}
};

WebMarkupContainer ajaxTable = new WebMarkupContainer("ajaxTable");
ajaxTable.setOutputMarkupId(true); // obrigatorio pq nao tem o
// atributo id com mesmo
// nome no html
add(ajaxTable);

// O componente PageableListView está dentro do

// entao deve ser adicionado ao WebMarkupContainer, não à página.
ajaxTable.add(view);

// O componente-chave para paginação-ajax, está aqui:
ajaxTable.add(new AjaxPagingNavigator("navegacao", view));
}
}
Pronto! Paginação ajax habilitada com sucesso! :)
Desta forma, ao navegar na lista somente a tabela com os dados será atualizada, através de requisições Ajax. Esta funcionalidade é muito útil quando se tem telas pesadas com diversos componentes, e não queremos atualizar a página inteira, ou quando simplesmente queremos dizer que a aplicação é Web 2.0 compliant.

Explicando um pouco o que foi feito:
  • Não foi preciso alterar qualquer trecho de código na table html, mas é necessário que a mesma esteja numa área atualizável div.
  • Não existe um AjaxPageableListView. O mesmo que utilizamos no primeiro exemplo foi utilizado aqui.
  • Como existe um div para ser atualizado assíncronamente, este precisa ser referenciado por um WebMarkupContainer, que conterá o novo código HTML após a requisição Ajax e substituirá o código anterior.
  • Qualquer componente que esteja dentro do div, deve ser adicionado no MarkupContainer, respeitando a árvore de componentes.
  • Configurei a propriedade
    outputMarkupId
    porque no HTML, nao coloquei o atributo id manualmente. Este método faz apenas isto. Utiliza o nome do componente para o atributo id.
  • Tanto a ListView como o Navigator, são adicionados no MarkupContainer.
  • Para a paginação efetivamente funcionar, deve-se utilizar o componente
    AjaxPagingNavigator
  • Pronto!
Até a próxima!

03 maio 2007

Apache Wicket: agora é oficial!

Tenho o prazer em anunciar o primeiro lançamento do Apache Wicket. Este release atende a todos os requisitos do Incubator PMC, e por isso, podemos considerar este o primeiro grande passo para o amadurecimento do framework, que a partir de agora, receberá maior atenção pela comunidade Java e Open Source. :)

Antes de anunciar para os brasileiros, um pouco da introdução (para aqueles que não leram meu primeiro post:

-= Apache Wicket =-
Apache Wicket é um framework web orientado a componentes, no momento sob os cuidados da Apache Software Foundation e sua incubadora. Com distinção entre lógica e código HTML, um modelo de dados em POJOs e ser livre de XML, o Apache Wicket simplifica e diverte o desenvolvimento de aplicações Web. Facilite seu desenvolvimento trocando complexidade por um poderoso mecanismo de reutilização de componentes escritos em puro Java e HTML.

Vocês podem encontrar outras informações aqui: http://incubator.apache.org/wicket

-= Este lançamento =-
Este é o primeiro de uma série de betas antes de uma confiança maior do time para finalizar o Apache Wicket 1.3 e lançá-lo sem bugs. Considere-o um Release Candidate.

- Migrando do Wicket 1.2 -
Aos que já utilizam o Wicket 1.2, o guia de migração para Wicket 1.3 encontra-se disponível no seguinte endereço: http://cwiki.apache.org/WICKET/migrate-13.html

- Download -
Este lançamento pode ser baixado no seguinde endereço:
http://people.apache.org/dist/incubator/wicket/apache-wicket-1.3.0-incubating-beta1/dist/

- Download com Maven -
Repositório:
http://people.apache.org/dist/incubator/wicket/apache-wicket-1.3.0-incubating-beta1/m2-repo/

- Bugs -
No caso de bugs serem encontrados, pedimos que submetam os mesmos no JIRA:
http://issues.apache.org/jira/browse/WICKET

Caso queira contribuir enviando patches de bugs, utilize a seguinte tag:
http://svn.apache.org/repos/asf/incubator/wicket/tags/wicket-1.3.0-incubating-beta-1/

-= Incubadora Apache Wicket =-
Maiores informações sobre o andamento do processo na incubadora:
http://incubator.apache.org/projects/wicket

[]'s!!
miojo

28 abril 2007

Wicket: Paginando listagens em 3 passos

Um dos pontos que mais se apanha para implementar quando do desenvolvimento de aplicações Web, é a paginação de lista de dados. Lembro-me dos tempos de Struts, onde a grande dúvida era usar ou não usar a antiga Display Tag. Infelizmente, trabalhando com frameworks action-based e código view em JSP/Taglib, implementar paginação é uma das tarefas mais chatas para a interface Web, pois exige uma cacetada de configuração na página e principalmente: suja todo o HTML e pronto, lá se foi o protótio do cliente e o designer não pode mais editar com um preview em mãos.

Algumas pessoas comentaram no primeiro post sobre Wicket pedindo que eu desse maiores detalhes de como funciona ou como se utiliza. Pensei bastante e achei melhor primeiro apresentar como o desenvolvedor utiliza o framework, antes de se preocupar em como o mesmo funciona "por trás das cortinas".

Para começar a enteder a paginação, primeiramente é importante entendermos o funcionamento do componente básico de repetição: ListView. Vejam o exemplo a seguir:

Pessoas.html
<table>
<tr>
<td>nome</td>
<td>idade</td>
</tr>
<tr wicket:id="lista">
<td><span wicket:id="nome">foo</span></td>
<td><span wicket:id="idade">12</span></td>
</tr>
</table>


Pessoas.java
public class Pessoas extends WebPage {
public Pessoas() {
List listaPessoas; /* obtem de algum lugar (Spring talvez) */
add(new ListView("lista", listaPessoas) {
protected void populateItem(ListItem item) {
Pessoa p = (Pessoa) item.getModelObject();
item.add(new Label("nome", p.getNome());
item.add(new Label("idade", p.getIdade());
}
});
}
}

Entendendo o funcionamento do ListView:
  • O bind foi feito com a tag <tr>, então para cada iteração na List, o ListView vai processar um ListItem para aquela tag.
  • O framework possui hierarquia de componentes, então vejam que o Label é adicionado no ListItem e não na ListView. Isto porque no HTML, temos e nome e idade dentro da lista.
  • Para cada objeto na lista, o framework coloca ele como ModelObject do ListItem. (farei um post futuramente sobre Models, explicando seu funcionamento e os diversos tipos).
O interessante aqui é enteder o básico do funcionamento da ListView, que pode ser aplicado a praticamente qualquer tag html que se deseja iterar e repetir.

Agora, vamos adicionar paginação nesta ListView. Para isto, precisamos executar alguns passos:
  1. Editar o HTML e acrescentar a barra de navegação.
  2. Converter a ListView para uma PageableListView.
  3. Adicionar em Java o componente PagingNavigator, realizando binding entre ele e a barra de navegação.
Passo 1
Utilizaremos aqui uma barra de navegação default do Wicket, sem customização. Deve-se adicionar na tabela a seguinte TR:
<tr>
<td colspan="2">
<span wicket:id="navegacao">aqui vai a barra de navegacao</span>
</td>
</tr>
Passo 2
Alterar a instanciação de uma ListView para uma PageableListView. Feito isto, é preciso informar no construtor, quantos itens serão apresentados por página:
PageableListView listView = null;
add(listView = new PageableListView("lista", listaPessoas, 2) { ...

Passo 3
Agora, falta apenas colocar o componente de navegação na classe Java:

     add(new PagingNavigator("navegacao", listView));

Pronto! Só reparem que no construtor de PagingNavigator, é preciso passar a referência para o PageableListView que será paginado por ele.

O que aprendemos?
Que utilizando Wicket, não sujamos nosso código HTML, nem mesmo para fazer paginação! É possível manter o HTML limpo para que os designers possam trabalhar sem problemas, e também, que nós programadores tenhamos apenas um ponto para modificar, como neste exemplo onde alteramos de uma simples listagem para uma listagem paginada, o controle dinâmico das telas: a classe Java! Pois em Wicket não existe configuração em XML. Este é todo o código necessário para que esta paginação funcione.

Confiram mais exemplos aqui:
Wicket Repeater Views

Até a próxima!

[]'s!
miojo

26 abril 2007

Wicket - Apresentação SouJava

Ano passado fiz uma apresentação sobre Wicket no SouJava em São Paulo, mas infelizmente não teve uma audiência muito grande, devido provavelmente ao pequeno público interessado em conhecer um framework Web com nome tão estranho. :)

(se eu fizer outra agora hoje, acredito que irá mais gente!)

Então, publico aqui os slides que mostrei na época, para dar uma idéia melhor do funcionamento e espero que acompanhem mais de perto o crescimento do Wicket!



[]'s!!!
miojo
Contato

Email:bruno.borges(at)gmail.com

LinkedIn: www.linkedin.com/in/brunocborges
Twitter: www.twitter.com/brunoborges
Comprei e Não Vou
Rio de Janeiro, RJ Brasil
Oracle
São Paulo, SP Brasil