Javafree

RMI no Tiger

Publicado por Tutoriais Admin em 04/10/2012 - 23.428 visualizações

1 - Introdução

Meu primeiro contato com RMI, foi na faculdade há quase três anos atrás. E de lá pra cá muitas coisas mudaram em sua implementação. Então, me veio à necessidade de estudar sistemas distribuídos, decidindo voltar aos estudos de RMI. Foi quando me deparei que em " quase " todos os tutorais em que pegava pra relembrar e estudar, não obtinha sucesso em suas implementações. Daí foi quando decidi pesquisar a documentação da versão que estou usando agora (JDK 1.5.0_01), onde observei as " pequenas " mudanças feitas desde a época em que estudei na faculdade.

1.1 - Objetivo

Este tutorial tem o objetivo de mostrar um " passo a passo " de como implementar uma simples aplicação distribuída com RMI no Tiger (Java 1.5.0 ou 5.0). E para fugir dos exemplos mais comumente encontrados, iremos fazer uma aplicação um pouco " diferente ", que também usa o mesmo host como cliente e servidor. E uma das diferenças entre nossa aplicação e as outras mais comumente encontradas, é que ao invés de trafegarmos uma String de uma ponta a outra (Servidor para Cliente), iremos trafegar um * Bean, dando asas à imaginação de quem está aprendendo agora.

* Bean? Um Bean é uma classe serializável que segue determinadas regras, como métodos get e set para cada uma de suas propriedades (encapsulamento).

Obs.: Não é meu objetivo esgotar o assunto que diz respeito à tecnologia RMI, mas sim dar um startup ou quem sabe, tirar as dúvidas de muitas pessoas que estão meio que " perdidas " como eu estava.

2 - Arquivos necessários

Nossa aplicação será composta dos seguintes arquivos:
- MeuBean.Java? Objeto Serializável ao qual iremos trafegar através de invocação remota
- Servidor.Java? Interface remota.
- ServidorImpl.Java? Classe servidora.Implementa a interface remota.
- Cliente.Java? Cliente que fará chamadas ao nosso objeto remoto (ServidorImpl).

3 - Passos para a construção
3.1 Implementar o Bean
3.2 Definir a interface Remota
3.3 Implementar o Servidor
3.4 Implementar o Cliente
3.5 Compilar nossas classes / interface
3.6 Rodar o Servidor
3.7 Rodar o Cliente
3.8 Conclusão

Então, abra seu editor predileto e mãos á massa...

3.1 - Implementar o Bean

O nosso Bean será uma classe simples com duas propriedades: Código e Descrição. Mas para que ele possa ser trafegado na rede, o mesmo deve ser serializável. E para isso, basta que nosso Bean implemente a interface Serializable, presente no pacote java.io.

Segue abaixo o código do mesmo:



3.2 - Definindo a interface remota

A interface remota é a alma de nossa aplicação, pois ela que vai conter as assinaturas dos métodos que nosso objeto remoto vai implementar e vai ser através dela que nosso cliente vai " enxergar " todos os métodos que estão disponíveis remotamente. E para que ela possa se dar a tal, ela deve implementar a interface Remote, disponível no pacote java.rmi. Como nossa interface é remota e vai servir de " espelho " para nosso objeto remoto, pode haver problemas de conexão ou coisas do gênero, portanto, todos os métodos de nossa interface devem estar preparados para lançar uma exceção caso tenhamos algum problema. Então, todos os métodos de nossa interface deverão lançar RemoteException, disponível também no pacote java.rmi.

Segue abaixo o código da nossa interface remota:



Como podemos observar, nossa interface tem apenas um método assinado e o mesmo retorna um objeto do tipo MeuBean e, como já falado, está preparado para lançar uma exceção do tipo RemoteException. Como nosso Bean não é um objeto remoto, ou seja, não herda de java.rmi.Remote, temos então que o retorno de nosso método getBean () será por valor, pois não geraremos um Stub * para o mesmo.

* Stub ? Funciona como um Proxy entre o cliente em nosso objeto remoto. Também é ele que codifica e decodifica (marshall e unmarshall) os parâmetros e retornos trafegados entre o cliente e o servidor.

3.3 - Implementar o Servidor

Nosso servidor será o objeto em que acessaremos remotamente para invocar seu (s) método (s). Para isso, ele deve implementar nossa interface remota, definida no tópico anterior, e seguir alguns passos:
A - Criar e exportar nosso objeto remoto
B - Registrar nosso objeto remoto e iniciar RMI Registry

Segue abaixo o código do servidor:



Como nossa classe ServidorImpl implementa a interface Servidor, então por obrigação implementamos o método getBean () presente da interface. Se você observar no método getBean () da classe ServidorImpl, verás que não está assinando que pode lançar RemoteException ou nenhuma outra exceção. Isso se deve ao fato de que a implementação de nosso método não lança RemoteException e nenhuma outra exceção checada.

A - Criar e exportar nosso objeto remoto

Para que tenhamos o serviço disponível, ou seja, o objeto pronto para receber chamadas remotas, criaremos uma instância do mesmo e exportaremos para a Java RMI Runtime e aí sim nosso objeto estará pronto para receber chamadas remotas.

Para isso, em nosso método inicia () temos:



O método estático UnicastRemoteObject.exportObject, exporta nosso objeto remoto (this, 0) em uma porta TCP anônima, devolvendo um Stub (do objeto remoto) ao qual passaremos para o cliente fazer chamadas remotas. O Stub retornado, implementa a mesma estrutura da interface remota, referenciando o objeto remoto e adicionando informações como host e porta para conexão.

Uma das melhorias no Tiger está bem aqui nesta parte. Quando uma aplicação exporta o objeto remoto e não encontra as classes de Stub, que eram e são necessárias nas versões anteriores, automaticamente é instanciado um objeto do tipo java.lang.reflect.Proxy que será um Stub para nosso objeto remoto, não necessitando assim das classes de Stub.

Obs.: Se seus objetos remotos tiverem clientes rodando em máquinas virtuais em versões anteriores ao Tiger, será necessário gerar as classes de Stub e talvez Esqueletons para os mesmos com o compilador rmic.

B - Registrar nosso objeto remoto e iniciar RMI Registry

Para que nosso cliente consiga fazer chamadas ao nosso objeto remoto, faz-se necessário que ele obtenha o Stub do objeto remoto, para isso temos que registrar nosso objeto remoto através do Stub do mesmo e nomeá-lo para que possamos o localizar o registro no servidor.

Para registrar o Stub de nosso objeto remoto, é usado o RMI registry. O RMI registry é o serviço de nomes que vai disponibilizar a referência remota para o Stub de nosso objeto remoto. Estando nosso objeto remoto registrado, nossos clientes podem fazer lookup (busca) do objeto pelo nome do mesmo, obtendo a referência e finalmente invocar seus métodos remotos.

Para fazermos isso, temos o seguinte código:



O método estático LocateRegistry.createRegistry (1000) retorna um Stub que implementa java.rmi.registry.Registry, " avisa " o registro que receberemos invocações e inicia o RMI Registry na porta especificada, no caso a 1000. O método bind é quem relaciona (liga) nosso Stub a um nome (" Servidor ") ao qual deverá ser chamado por invocação remota.

3.4 - Implementar o Cliente

O nosso cliente será o responsável por fazer as chamadas remotas ao nosso objeto remoto. Para isso, ele deve obter o Stub de nosso objeto remoto no servidor fazendo a chamada pelo nome atribuído ao mesmo, e então fazer invocações remotas aos métodos remotos disponíveis através do Stub. Mas para que nosso cliente possa obter nosso Bean e saber quais são os métodos que estão disponíveis a ele, faz-se necessário que ele conheça nossa classe Bean e nossa interface remota. E para isso basta que ele tenha uma cópia de nossa interface remota (Servidor) e de nosso Bean (MeuBean).

Segue o código do cliente:



O cliente primeiro obtém o Stub do registro através do método estático LocateRegistry.getRegistry passando como parâmetro o host e a porta *. Depois invoca o método remoto registry.lookup, passando como parâmetro o nome ao qual foi registrado nosso objeto remoto no servidor, para obter o Stub. Como em nosso exemplo estamos executando o cliente e o servidor mesma máquina, foram passados como parâmetros o host " localhost " e a porta 1000, que poderia ser outra. Mas se seu servidor estiver funcionando em um host que não seja o localhost, basta colocar o nome da máquina ou o IP da mesma no local do host. Então já que já temos nosso canal de comunicação com o servidor, basta-nos agora invocar o método remoto getBean (). Então através do método getBean () obteremos uma cópia de nosso bean que foi instanciado lá no servidor.

* Obs.: Se não for especificada nenhuma porta, o RMI Registry rodará por padrão na porta 1099.
3.5 - Compilar nossas classes / interface



3.6 - Rodar o servidor



Deverá sair em sua console a seguinte mensagem:
Servidor iniciado...

A partir de agora seu servidor estará pronto para receber requisições. O servidor ficará rodando até que o usuário decida finalizá-lo, geralmente matando o processo (CTRL + C).

3.7 - Rodar o Cliente



E pronto, deve sair em seu console a seguinte mensagem:


3.8 - Conclusão

Bom pessoal, esse é o meu primeiro tutorial e espero ter atingido, sanado dúvidas ou até iniciado muitos " javeiros " nesta maravilha chamada RMI.

Autor

Paulo Henrique Borges Melo (paulohbmetal@yahoo.com.br) é Bacharel em Ciência da Computação e Sun Certified Java Programmer