Olá a todos :o)
Esta é a minha primeira mensagem neste fórum, e eu gostaria de divulgar um projeto que eu desenvolvi para substituir o RMI nativo do Java - o projeto teve o código-fonte aberto hoje e foi licenciando sob LGPL.
Estou divulgando neste fórum pois acredito que projetos abertos só crescem com a participação de todos e com o contato com a comunidade.
Acredito não estar fazendo mal ao fórum. Mas, em todo caso, desculpem-me pois jamais tive esta intenção.
Vamos ao que interessa: a proposta é re-escrever o RMI para resolver todos os problemas que a implementação original do RMI traz.
Um deles - que torna o RMI tão impopular - é o uso na Internet, e esse é o principal foco do projeto.
O problema do RMI
Quando você faz chamadas via RMI não é possível garantir de que maneira ela vai ser transportada na camada de comunicação. E quando perdemos controle sobre isso, talvez nosso software não funcione corretamente em todos os ambientes em que gostariamos.
A situação otimizada quando o usuário da aplicação está se conectando através da Internet é que a latência da comunicação seja mínima e que nosso cliente não precise alterar nada na topologia da sua rede para poder se conectar.
Com o RMI perdemos nestes dois pontos: a comunicação via RMI é custosa (utilizando muita banda - as vezes causando uma latência indesejada) e requer que o usuário final tenha um IP válido com algumas portas abertas (e para isto talvez ele tenha que alterar a topologia da sua rede).
Destes dois problemas, uso excessivo de banda não é o pior, mas pode ser otimizado.
O maior problema é quando o usuário precisa reconfigurar sua rede por causa do seu aplicativo que utiliza RMI - e a consequência disso pode ser óbvia: a não utilização do aplicativo.
O problema na camada de comunicação do RMI é que praticamente para uma invocação/retorno, um novo socket é criado; os sockets não seguem uma direção única e tanto o cliente como o servidor podem tentar conectar um no outro.
Listeners remotos (callbacks) também criam um problemão; já que sempre são chamados na direção servidor->cliente; fazendo, portanto, com que o servidor tente conectar no cliente, obrigando que o cliente tenha um IP válido e que a porta esteja disponível para conexão - o que não é o ideal na Internet, já que os clientes muitas vezes estão em redes locais, atrás de NATs/roteadores ou firewalls.
Quer dizer, se você tem uma aplicação voltada para o usuário final que use callbacks, sempre que um novo usuário quiser utilizar a aplicação ele vai ter que pedir pro administrador da rede criar uma regra no NAT apontando uma porta do IP válido para o IP interno dele. Inviável para uma aplicação desktop, não acha?
Tudo isso acontece por um único motivo - bem conhecido, na verdade - o RMI originalmente não foi feito para ser utilizado na Internet.
Solução “Sun”: Sobreescrever as Factorys
O RMI oferece meios para trocar as Factorys dos sockets. Parece ideal para resolver todo o problema, mas não é. O RMI permite, através destas Factorys, que nós manipulemos os dados trafegados pelas streams dos sockets e as propriedades internas dos novos sockets.
Porém, quem continua decidindo até quando manter um socket ativo ou quando criar novos ainda é o RMI.
Minha proposta
A minha proposta é bastante clara: re-implementar o RMI de uma maneira que possibilite que as chamadas sejam feitas através da Internet e minimize o uso de banda.
Esta nova implementação deve oferecer uma API muito parecida com o RMI nativo, exigindo a troca de apenas poucas linhas de código para uma re-adaptação de qualquer aplicativo.
As aplicações comerciais mais populares utilizam um conceito muito simples para se comunicar pela Internet: sempre que um cliente quer se comunicar com o servidor, o cliente é o responsável por fazer a conexão, e é através desta mesma conexão que o servidor envia dados para o cliente.
O servidor apenas deve estar ouvindo em alguma porta específica pré-determinada. E utilizando poucas portas fixas no servidor podemos criar regras para que o firewall permita a entrada de novas conexões para atender os clientes.
Depois que o cliente já estiver conectado, esta conexão deve permanecer aberta durante toda sessão de troca de dados entre o cliente e o servidor (ou até que a aplicação permita que a conexão seja fechada). Desta forma o servidor nunca irá precisar abrir uma conexão no sentido servidor->cliente, pois é possível utilizar a conexão já existente. E não precisando abrir novas conexões, o cliente não precisa se preocupar com firewalls - resolvendo o maior problema do RMI.
Melhorias
A minha idéia não é seguir a risca a implementação padrão da Sun. A proposta do projeto é melhorar tudo que for possível, inclusive a API.
Por exemplo, minha implementação permite que a aplicação tenha acesso a alguns eventos de conexão - quando uma conexão inicia ou acaba. Isto é muito útil para resolver antigos problemas, onde o servidor tinha que ficar sempre invocando algum método remoto para saber se o cliente continua respondendo - e que custa alguma banda preciosa.
Experiência
O projeto já vinha sendo testado e utilizado há alguns meses em projetos pessoais - tal como este jogo http://lipe.advant.com.br/dalmuti que utiliza Java WebStart + LipeRMI + SWT.
O resultado do LipeRMI hoje é um projeto maduro e suficientemente bom para ser utilizado em aplicações robustas.
Porém certamente ainda pode ser muito melhorado e eu estou procurando pessoas pra ajudar a divulgar o projeto, pois acredito que testando, utilizando, enviando sugestões e reportando bugs é a melhor maneira para se manter um projeto open-source vivo e com qualidade.
O link para a página oficial do LipeRMI é http://lipermi.sourceforge.net
Qualquer contribuição será muito bem vinda :o)
–
[size=7]E desculpem, novamente, por utilizar o fórum para divulgação. Meu objetivo não é utilizar o fórum como meio de propaganda para um projeto pessoal, e sim melhorar a qualidade de projetos open source com a participação da comunidade - que no caso de vocês do GUJ é a maior de todas :oP[/size]