Вы находитесь на странице: 1из 6

Introduo Computao Distribuida com RMI

A tecnologia RMI - Remote Method Invocation (Invocao de Mtodos Remotos), foi


primeiramente introduzida no Java, no JDK verso 1.1, elevando a programao para
redes em um patamar mais elevado. Apesar do RMI ser relativamente fcil, ele pe o
desenvolvedor Java frente um novo paradigma, o mundo da computao de objetos
distribudos. Este guia prtico vai lhe introduzir esta tecnologia verstil, que melhorou
muito desde sua primeira verso.
Objetivo
O principal objetivo para os criadores (designers) do RMI era permitir os
programadores a desenvolverem programas distribudos em Java com a mesma sintaxe
e semntica usada em programas no-distribudos. Para isso, eles tiveram que mapear
cuidadosamente como classes Java e objetos trabalham em uma nica Java Virtual
Machine (JVM) para um novo modelo de como as classes e objetos trabalhariam num
ambiente distribudo de computao (mltiplas JVMs). Os arquitetos do RMI tentaram
fazer com que o uso dos objetos distribudos em Java fosse similar ao uso de objetos
Java locais. Esta seo introduz a arquitetura RMI da perspectiva dos objetos Java
remotos distribudos, e explora as diferenas de comportamento com objetos locais. A
arquitetura RMI define como os objetos se comportam, como e quando excees podem
ocorrer, como a memria gerenciada e como os parmetros so passados e retornados
de mtodos remotos.
Arquitetura Java RMI
A arquitetura RMI estende a segurana e robustez da arquitetura Java para o mundo da
computao distribuda.
Interfaces: O corao do RMI
A arquitetura RMI baseada em um importante princpio: a definio do
comportamento e a implementao do comportamento so conceitos separados. RMI
permite que o cdigo que define o comportamento e o cdigo que implementa o
comportamento permanecerem separados e rodarem em JVMs separadas. Em RMI, a
definio do servio remoto codificada usando uma interface Java. A implementao
do servio remoto codificada em uma classe. Logo, a chave para se entender o RMI
lembrar que as interfaces definem o comportamento e as classes definem a
implementao. A classe que implementa o comportamento roda do lado do servidor
RMI. A classe que roda no cliente atua como um Proxy para o servio remoto. Veja o
seguinte diagrama: O programa cliente faz chamadas de mtodos pelo objeto
Proxy, o RMI envia a requisio para a JVM remota e redireciona para a
implementao. Qualquer valor retornado pela implementao devolvido ao Proxy e
ento ao programa cliente.
Arquitetura de Camadas do RMI
Com o entendimento da arquitetura RMI num alto nvel, vamos dar uma breve olhada
na sua implementao. A implementao do RMI essencialmente feita de trs
camadas de abstrao. A camada Stub e Skeleton est abaixo dos olhos do
desenvolvedor. Esta camada intercepta as chamadas de mtodos feitas pelo cliente para
que a varivel de referncia da interface redirecione essas chamadas para o servio RMI
remoto. A prxima camada a Remote Reference Layer. Esta camada sabe como
interpretar e gerencias referncias feitas dos clientes para os objetos do servio remoto.
A conexo do cliente ao servidor Unicast (uma-para-um). A camada de transporte
baseada nas conexes TCP/IP entre as maquinas em uma rede. Usando essa arquitetura
de camadas, cada uma das camadas poderia ser facilmente melhorada ou substituda
sem afetar o resto do sistema. Por exemplo, a camada de transporte poderia ser
substituda por uma camada que implemente conexes UDP/IP, sem afetar as camadas
superiores.
Nomeando Objetos Remotos
Como um cliente acha o servio remoto RMI? Os clientes acham os servios remotos
usando o servio de nomeao ou diretrio (naming or directory). Isso parece um pouco
redundante, mas o servio de nomeao ou diretrio roda como um endereo bem
formado (host:port). O RMI pode usar diferentes tipos de servios de diretrio,
incluindo o JNDI. O prprio RMI inclue um simples servio, chamado de RMI
Registry. O RMI Registry roda em cada maquina que hospeda o servio remoto, por
definio na porta 1099. Numa mquina host, um programa servidor cria um servio
remoto, primeiramente criando o objeto que implemente aquele servio. Em seguida ele
exporta aquele objeto para o RMI. Quando o objeto exportado o RMI cria um servio
que aguarda as conexes do cliente. O servidor registra o objeto no RMI Registry, com
um nome pblico. No lado do cliente o RMI Registry acessado atravs da classe
esttica Naming. Ela provm o mtodo lookup( ), que o cliente usa para requisitar o
registro. Esse mtodo aceita a URL que especifica o nome do servidor e o nome do
servio desejado. O mtodo retorna uma referncia remota para o objeto do servio. A
URL formada como seguinte:
view plainprint?
1. rmi://<host_name>[:port_number]/<service_name>

Usando o RMI
Agora vamos trabalhar com um sistema que realmente implementa um sistema com
RMI. Vamos criar um aplicativo simples, cliente e servidor, que executa mtodos do
objeto remoto. Para tanto no necessitamos de duas mquinas distintas ou com IP
distintos. O exemplo pode ser rodado na mesma mquina, pois o RMI sabe como
trabalhar com isso, mesmo que o host e o cliente sejam na mesma localidade. Um
sistema RMI composto de vrias partes:
Definio das interfaces para os servios remotos
Implementaes dos servios remotos
Arquivos de Stub e Skeletons
Um servidor para hospedar os servios remotos
Um servio de RMI Naming que permite o cliente achar os servios remotos
Um provedor de arquivos de classes (servidor http ou ftp)
Um programa cliente que necessita os servios remotos
Criando seu aplicativo com RMI
Agora iremos, de fato, criar um sistema que implemente o RMI, utilizando-se de um
programa cliente e um programa servidor. No utilizaremos um servidor FTP ou HTTP,
no entanto utilizaremos os programas na mesma mquina e uma mesma estrutura de
diretrios. Os passos a serem seguidos agora so:
Escrever e compilar o cdigo Java da interface
Escrever e compilar o cdigo Java das implementaes das classes
Gerar as classes Stub e Skeleton das classes de implementao Crie um diretrio para
salvar todos os seus arquivos de projeto. Voc pode fazer o download do cdigo fonte
usado nesse tutorial.
Interfaces
O primeiro passo, como dito, ser criar a interface e compil-la. A interface define todas
as funcionalidades remotas oferecidas pelo servio. Nomeio o arquivo como:
Mensageiro.java.
view plainprint?
1. import java.rmi.Remote;
2. import java.rmi.RemoteException;
3.
4. public interface Mensageiro extends Remote {
5.
6. public void enviarMensagem( String msg ) throws RemoteException;
7. public String lerMensagem() throws RemoteException;
8. }

Perceba que esta interface estende a classe Remote, e cada assinatura de mtodo declara
as funcionalidades do servio, e que podem gerar uma exceo RemoteException. Salve
este arquivo (Mensageiro.java) no seu diretrio e compile, com a seguinte linha de
comando:
view plainprint?
1. javac Mensageiro.java


Implementao
Agora, voc dever escrever a implementao para o servio remoto, ou seja, o cdigo a
ser executado no ambiente remoto. Nomeia o arquivo como: MensageiroImpl.java.
view plainprint?
1. import java.rmi.RemoteException;
2. import java.rmi.server.UnicastRemoteObject;
3.
4. public class MensageiroImpl extends UnicastRemoteObject implements Mensageiro
{
5.
6. public MensageiroImpl() throws RemoteException {
7. super();
8. }
9.
10. public void enviarMensagem( String msg ) throws RemoteException {
11. System.out.println( msg );
12. }
13.
14. public String lerMensagem() throws RemoteException {
15. return "This is not a Hello World! message";
16. }
17. }

Salve este arquivo (MensageiroImpl.java) no seu diretrio e compile, com a seguinte
linha de comando:
view plainprint?
1. javac MensageiroImpl.java

Observe que a classe se utiliza (estende) da classe UnicastRemoteObject para linkar
com o sistema RMI. Neste exemplo a classe estende a classe UnicastRemoteObject
diretamente. Isto no realmente necessrio, mas essa discuso fica para uma prxima
etapa. Quando uma classe estende a classe UnicastRemoteObject, ele deve prover um
construtor que declare que ele pode lanar uma exceo RemoteException, pois quando
o mtodo super( ) chamado, ele ativa o cdigo em UnicastRemoteObject, que executa
o link RMI e a iniciao do objeto remoto.
Stubs e Skeletons
Gere os arquivos Stubs e Skeletons da classe de implementao que roda no servidor.
Para tanto, execute o comando rmic, compilador RMI do JDK.
view plainprint?
1. rmic MensageiroImpl

Aps a execuo deste comando, voc deveria ver no seu diretrio os arquivos
Mensageiro_Stub.class, Mensageiro_Skeleton.class. Servidor O servio remoto RMI
deve ser hospedado em um processo servidor. A classe MensageiroServer um servidor
bem simples, que prov servios essenciais. Salve o arquivo como:
MensageiroServer.java.
view plainprint?
1. import java.rmi.Naming;
2.
3. public class MensageiroServer {
4.
5. public MensageiroServer() {
6. try {
7. Mensageiro m = new MensageiroImpl();
8. Naming.rebind("rmi://localhost:1099/MensageiroService", m);
9. }
10. catch( Exception e ) {
11. System.out.println( "Trouble: " + e );
12. }
13. }
14.
15. public static void main(String[] args) {
16. new MensageiroServer();
17. }
18. }

Salve este arquivo (MensageiroServer.java) no seu diretrio e compile, com a seguinte
linha de comando: > javac MensageiroServer.java
Cliente
O cdigo fonte para o cliente o seguinte. Salve o arquivo como:
MensageiroClient.java.
view plainprint?
1. import java.rmi.Naming;
2. import java.rmi.RemoteException;
3. import java.rmi.NotBoundException;
4. import java.net.MalformedURLException;
5.
6. public class MensageiroClient {
7.
8. public static void main( String args[] ) {
9. try {
10. Mensageiro m = (Mensageiro) Naming.lookup( "rmi://localhost/Mensag
eiroService" );
11. System.out.println( m.lerMensagem() );
12. m.enviarMensagem( "Hello World!" );
13. }
14. catch( MalformedURLException e ) {
15. System.out.println();
16. System.out.println( "MalformedURLException: " + e.toString() );
17. }
18. catch( RemoteException e ) {
19. System.out.println();
20. System.out.println( "RemoteException: " + e.toString() );
21. }
22. catch( NotBoundException e ) {
23. System.out.println();
24. System.out.println( "NotBoundException: " + e.toString() );
25. }
26. catch( Exception e ) {
27. System.out.println();
28. System.out.println( "Exception: " + e.toString() );
29. }
30. }
31. }

Salve este arquivo (MensageiroClient.java) no seu diretrio e compile, com a seguinte
linha de comando:
view plainprint?
1. javac MensageiroClient.java


Rodando o sistema RMI
Agora que todos os arquivos do projeto de exemplo foram criados e devidamente
compilados, estamos prontos para rodar o sistema! Voc precisar abrir trs diferentes
consoles do MS-DOS no seu Windows, ou outro, caso utilize um diferente sistema
operacional. Em um dos consoles vai rodar o programa servidor, no outro o cliente e no
terceiro o RMI Registry. Inicie com o RMI Registry. Voc deve estar no mesmo
diretrio em que esto gravados seus arquivos para rodar o aplicativo. Execute a
seguinte linha de comando:
view plainprint?
1. rmiregistry

Isso ir iniciar o RMI Registry e rod-lo. No segundo console vamos executar o
programa servidor. Voc deve estar no mesmo diretrio em que esto gravados seus
arquivos para rodar o aplicativo. Execute o seguinte comando:
view plainprint?
1. java MensageiroServer

Isso ir iniciar, carregar a implementao na memria e esperar pela conexo cliente.
No ltimo console, rode o programa cliente. Voc deve estar no mesmo diretrio em
que esto gravados seus arquivos para rodar o aplicativo. Excute o comando:
view plainprint?
1. java MensageiroClient

Se tudo correr bem, que o que esperamos e o que deveria acontecer, a seguinte sada
ser gerada nos consoles 2 (servidor) e 3 (cliente). No console 2 (servidor):
view plainprint?
1. Hellow World!

No console 3 (cliente):
view plainprint?
1. This is not a Hello World! message

isso a. Voc acabou de criar um sistema utilizando a tecnologia RMI. Apesar de voc
ter rodado os programas na mesma mquina, o RMI usa a pilha de rede TCP/IP para se
comunicar entre as trs diferentes instncias da JVM. Espero que tenham gostado e
aprendido com esse pequeno exemplo de como se usar o RMI.