genesis 3.0-EA3: suporte Swing e Java 5

agosto 22nd, 2006

Finalmente, após oito meses de trabalho e contratempos, está disponível a versão 3.0-EA3 do genesis. Toda a documentação foi reformulada e há versões em inglês e português.

As novidades mais legais dessa versão são o binding Swing e o suporte a anotações do Java 5 (que também funcionam com Java 1.4 da mesma maneira). O conceito do binding no genesis é único porque você pode trabalhar com JavaBeans sem amarrar a lógica da sua aplicação a API gráfica (Swing e Thinlet, no momento). Por exemplo, pode-se codificar um form assim :


@Form
public class LoginForm {
   private String usuario;
   private String senha;

   public String getUsuario() {
      return usuario;
   }

   public void setUsuario(String usuario) {
      this.usuario = usuario;
   }

   public String getSenha() {
      return senha;
   }

   public void setSenha(String senha) {
      this.senha = senha;
   }

   @Action
   public void login() {
      System.out.println(usuario);
      System.out.println(senha);
   }

   @Action
   public void limpar() {
      setUsuario(null);
      setSenha(null);
   }
}

E ligá-lo a uma interface gráfica em Swing assim:


@ViewHandler
public class LoginSwingView extends JDialog {
   public LoginSwingView() {
      super(new JFrame(), "Login");
      initComponents();

      SwingBinder binder = new SwingBinder(this, new LoginForm());
      binder.bind();
   }

   private void initComponents() {
      getContentPane().setLayout(new GridLayout(2, 1));

      JPanel panelDados = new JPanel();
      panelDados.setLayout(new GridLayout(2, 2, 5, 5));

      JLabel labelUsuario = new JLabel();
      labelUsuario.setText("Usuário");
      panelDados.add(labelUsuario);

      JTextField usuario = new JTextField();
      usuario.setName("usuario");
      panelDados.add(usuario);

      JLabel labelSenha = new JLabel();
      labelSenha.setText("Senha");
      panelDados.add(labelSenha);

      JPasswordField senha = new JPasswordField();
      senha.setName("senha");
      panelDados.add(senha);

      getContentPane().add(panelDados);

      JPanel panelBotoes = new JPanel();

      JButton login = new JButton();
      login.setText("Login");
      login.setName("login");
      panelBotoes.add(login);

      JButton limpar = new JButton();
      limpar.setText("Limpar");
      limpar.setName("limpar");
      panelBotoes.add(limpar);

      getContentPane().add(panelBotoes);

      pack();

      setLocationRelativeTo(null);

      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }

   public static void main(String args[]) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            new LoginSwingView().setVisible(true);
         }
      });
   }
}

Ou seja, diferente de outros frameworks, o genesis não requer o uso de componentes proprietários e você pode usar tranquilamente o Matisse ou o VEP para desenhar suas telas, bastando setar o name dos componentes de acordo com o seu form. Mais detalhes sobre como o binding funciona podem ser encontrados na documentação.

Closures em Java

agosto 18th, 2006

Alguns dos indivíduos mais inteligentes da comunidade, como Gilad Bracha, Neal Gafter e James Gosling escreveram uma proposta para adicionar closures a linguagem Java, conforme postado pelo Peter von der Ahé, que também participou da escrita do PDF. Espero que criem logo essa JSR… :-)

Efeitos colaterais da mudanca de class literal no Java 5

agosto 17th, 2006

Acabo de postar no meu blog no java.net sobre a mudança no tratamento de class literals no Java 5 e seus efeitos colaterais nocivos. Basicamente, o uso de uma expressão como MinhaClasse.class não garante que a classe foi inicializada, i.e., que seu bloco static e membros estáticos foram inicializados. Confira!

Convertendo Strings para objetos

agosto 9th, 2006

Aproveitando esse blog para fazer uma pesquisa de opinião: como vocês fazem parsing e/ou geram aqueles arquivos texto ou mensagens que tem até doc do Word do layout de tão complexos que são? Fazem na mão, usam uma API que retorna “tokens” convertidos ou o que?

Pergunto porque desenvolvi uma API pequena (7 classes so far) em que você configura o layout via xml e como mapear as propriedades para seus beans e ele te retorna um bean ou uma Collection. Ou seja, ao invés de fazer uma leitura nojentinha com posições, conversões e afins, você carrega o xml com um método, cria um objeto capaz de ler o layout, chama um parse(Reader) e tem a sua NotaFiscal com instâncias de ItemNotaFiscal e instâncias de outras classes do seu domínio configuradas.

Se houver interesse, pretendo (não é promessa!) liberar como open-source. Aguardo o feedback :-)

Quando o Google te atrapalha :-)

agosto 9th, 2006

Engraçado como é ruim ter um post bem colocado no Google para um assunto genérico. Se você pesquisar por como fazer cronogramas, o meu post “A arte de fazer cronogramas” aparece em segundo ou terceiro (varia de vez em quando). E, com isso, como vocês podem ver nos comentários do post, aparecem pessoas querendo saber como montar escalas ou coisa do gênero :-)

Quando um OutOfMemoryError nao e falta de memoria…

agosto 4th, 2006

Hoje de manhã, Bruno Borges, co-worker da Summa, me mostrou um site duma empresa famosa que exibia um stack trace com OutOfMemoryError. Contudo, a mensagem exibida me lembrou de um problema que solucionei no ano passado e que mostra que nem sempre um OutOfMemoryError tem a ver com falta de memória propriamente dita:


java.lang.OutOfMemoryError: unable to create new native thread

Normalmente esse erro é causado por um problema um tanto quanto raro em Java: thread leaks. Isso pode acontecer se threads auxiliares são criadas com frequência e se elas não forem corretamente encerradas. Geralmente as threads encontram-se em wait(), mas a condição que deveria acordá-las nunca mais vai ocorrer.

A melhor forma de resolver esse problema é utilizar um profiler para identificar onde as threads que permanecem ativas são criadas e depois utilizar um debugger para investigar por que elas não são encerradas como esperado. Taí a dica ;-)

Resolvendo problemas de lock acessando email

agosto 2nd, 2006

Resolvi esses dias um problema interessante. Num determinado projeto, existem serviços de integração rodando num JBoss e alguns deles são baseados no processamento de arquivos anexados em emails. No entanto, as vezes essas threads simplesmente paravam de emitir log e, como o número de transações do sistema é alto e o log é rotacionado após um certo tamanho, não era possível determinar a causa.

Antes mesmo que eu reconfigurasse o log para poder diagnosticar o que estava acontecendo, percebi que a thread congelava após tentar efetuar login no servidor SMTP. Verifiquei a API em busca de uma maneira padrão de realizar as operações com timeout, mas não encontrei. Contudo, a implementação da Sun possui duas propriedades que permitem controlar o timeout do acesso a uma caixa de mensagens POP3: mail.pop3.connectiontimeout e mail.pop3.timeout, conforme documentado aqui.

A parte “assustadora” dessa correção foi descobrir que o padrão dessas propriedades é nunca causar timeout. Logo, as threads iam ficar congeladas até o próximo deploy/restart/reboot. Mais uma lição aprendida.

Melhorando a serializacao de objetos imutaveis

julho 28th, 2006

Criei um issue no JIRA do JBoss Serialization para melhorar a serialização de objetos imutáveis. Enquanto fazia algumas otimizações em um sistema que utiliza RMI – como protocolo de comunicação com um EJB remoto -, percebi que as chamadas problemáticas eram grandes somente porque continham diversos objetos imutáveis semanticamente iguais.

É muito comum isso ocorrer em função de como geramos instâncias dos tipos básicos na maior parte dos casos. Provavelmente as três maiores fontes de dados hoje são dados entrados pelo usuário, arquivos/documentos de terceiros e dados do banco. Em todos os três casos, as APIs e soluções de parsing utilizadas em quase sua totalidade não fazem cache de instâncias, até porque isso normalmente é desnecessário e sujeito a erros.

Por exemplo, se você estiver usando o Hibernate para ler o bean Produto que, entre outros atributos, possui um atributo BigDecimal que representa a quantidade em estoque e houver 1000 produtos que possuem um estoque de 5.5 unidades 1000 instâncias de BigDecimal 5.5 serão criadas em RAM. Em termos de memória isso não é normalmente relevante, mas quando se tenta serializar mil instâncias ao invés de uma instáncia repetida 1000 vezes, a diferença é brutal:


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class BigDecimalSerializationTest {
   public static void main(String[] args) throws IOException {
      List instances = new ArrayList();

      for (int i = 0; i < 1000; i++) {
         instances.add(new BigDecimal("5.5"));
      }

      imprimeTamanhoSerializado(instances);

      Collections.fill(instances, new BigDecimal("5.5"));

      imprimeTamanhoSerializado(instances);
   }

   private static void imprimeTamanhoSerializado(final Collection instances)
         throws IOException {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);

      for (Iterator i = instances.iterator(); i.hasNext();) {
         oos.writeObject(i.next());
      }

      oos.close();

      System.out.println(baos.size());
   }
}

A saída na minha máquina para o teste acima é:


48242
5285

No caso específico que estava otimizando, após considerar o uso de um aspecto, descobri que a maior parte das instâncias era gerado num processo de parsing manual de um arquivo. O simples uso de um Map<String, BigDecimal> e afins para cache das instâncias foi suficiente para eliminar a repetição e trazer um ganho de até 60% em alguns casos.

Contudo, uma otimização assim deveria estar implementada na API de serialização e por isso abri esse issue no JBoss Serialization, que já é superior a API de serialização padrão com respeito ao tamanho em bytes gerado.

Polemica no post “The language barrier”

julho 28th, 2006

Por essa eu não esperava: a maior parte dos comentários no meu post The language barrier acha que todo mundo tinha mais é que saber inglês e pronto. Para quem não consegue ler inglês, o post fala sobre a dificuldade que o indivíduo com potencial tem de se tornar um bom desenvolvedor pela falta de material em português, especialmente javadocs, livros e material original escrito na nossa língua.

A maioria dos que responderam pensam que é obrigação de quem trabalha com TI saber inglês, que não saber não ajuda o mercado global, que ter um blog no seu idioma nativo é perda de tempo e coisas do tipo. Sinceramente, se é assim, eu acho que a gente devia acabar com todo o material em português sobre TI e ainda tornar o inglês obrigatório para o indivíduo ser aceito na faculdade. Pelo menos assim ele não vai criar falsas esperanças achando que vai ser alguma coisa se não souber o idioma.

Triste, triste, muito triste…

GPL3, draft 2

julho 27th, 2006

Se voê usa ou cria software open-source, deveria visitar o site da versão 3 da licença GPL. Para aqueles que não sabem, com exceção dos projetos da Apache, do Spring (que usa licença Apache também) e dos projetos da Sun, a grande maioria dos frameworks e ferramentas livres que utilizamos estão licenciados sob a LGPL (JBoss, Hibernate) ou a GPL (MySQL).

O grande objetivo dessa atualização da licença é é cobrir os novos cenários existentes, como uso de tecnologias para proteção de diretos (DRM) ou novos mecanismos de distribuição, como os torrents. Vale a pena ler.