












Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Tutorial de apoio para implementação de RMI em JAVA
Tipologia: Notas de estudo
1 / 20
Esta página não é visível na pré-visualização
Não perca as partes importantes!













by lufer, Carlos Castro , Sandra Melo
(v.1.1)
Este documento resultou do tratamento e compilação de informação vária sobre JAVA RMI, existente em livros da especialidade, acetatos das aulas, URLs da Web e outras fontes. Esta versão teve a colaboração dos alunos Sandra Melo e Carlos Castro do curso de SIG.
Referências:
Tutorais:
A tecnologia RMI - Remote Method Invocation (Invocação de Métodos Remotos), surge na expectativa de, por um lado acompanhar a força do desenvolvimento apoiado em arquitecturas RPC (Remote Procedure Call), no mundo da Programação Orientada a Objectos, e por outro, suportando o desenvolvimento distribuído em JAVA, herdando o que de melhor estas tecnologia e paradigma oferecem.
O JAVA RMI surgiu logo com a versão Java JDK 1.1, e tem vindo a sofrer pequenas alterações à medida que novos pacotes JAVA são lançados. Embora a portabilidade de soluções desenvolvidas não esteja saudavelmente garantida entre versões JAVA (entenda-se, JVM - Máquinas Virtuais JAVA), a arquitectura RMI assenta num padrão de desenvolvimento que se tem respeitado.
Apresentação
O principal objectivo do JAVA RMI é possibilitar o desenvolvimento de aplicações distribuídas em JAVA, utilizando a sintaxe e semântica usada nos programas não distribuídos. Pretende-se utilizar métodos de objectos remotos a partir de qualquer JVM, residentes ou não na mesma
máquina. Praticamente todas as “virtudes” da tecnologia JAVA são mantidas, como é o caso do portabilidade, segurança e polimorfismo. Interagir com sistemas legados (via JNI, JDBC, etc.), com outros objectos existentes, etc., é uma tarefa suportada. Os arquitectos do RMI tentaram fazer com que o uso dos objectos distribuídos em Java fosse similar ao uso de objectos Java locais.
A arquitectura RMI define como os objectos se comportam (através de JAVA Interfaces), como e quando excepções podem ocorrer, como a memória é gerida e como os parâmetros são passados e retornados entre métodos remotos.
Arquitectura JAVA RMI
A arquitectura RMI é baseada num importante princípio: a definição do comportamento e a implementação do comportamento são conceitos separados. O RMI permite que o código que define o comportamento e o código que implementa o comportamento permaneçam separados e corram em Máquinas Virtuais separadas separadas.
Em RMI, a definição do serviço remoto é codificada através de uma Interface Java, enquanto a sua implementação (desse mesmo serviço remoto) é codificada numa classe. Logo, a chave para se entender o RMI é recordar que as Interfaces definem o comportamento e as classes definem a implementação.
A classe que implementa o comportamento (i.e, os métodos ou serviços que se pretendem disponibilizar) executa no lado do servidor RMI. A classe que executa no cliente actua como um Proxy para o serviço remoto, tal como é representado no seguinte diagrama:
O programa cliente faz chamadas de métodos pelo objecto Proxy, o RMI envia a requisição para a JVM remota e redirecciona para a implementação. Qualquer valor devolvido (return) pelo servidor é devolvido ao Proxy e depois ao programa cliente.
Um objecto RMI, ao poder ser evocado remotamente, tem de ser implementado seguindo as seguintes especificações RMI:
Numa máquina host, o servidor cria o objecto que implementa um dado serviço remoto pretendido. Depois regista-o no RMI Registry , com um nome público.
No lado do cliente o RMI Registry é acedido através da classe estática Naming. Ela possui, entre outros métodos, o método lookup( ) , que o cliente usa para procurar o registro. Esse método aceita a URL que especifica o nome do servidor e o nome do serviço desejado. O método retorna uma referência remota para o objecto do serviço. A URL tem o seguinte aspecto:
rmi://<host_name>[:port_number]/<service_name>
“Receita” para programar RMI
Para este tópico vamos utilizar o exemplo Mensageiro (também analisado nas aulas e cujo código se encontra na página da disciplina), utilizado pelos tutoriais Java na demonstração de vários processos de desenvolvimento. Para isso não necessitamos obrigatoriamente de duas máquinas distintas ou com IP distintos. O exemplo pode ser executado na mesma máquina, pois o RMI sabe como lidar com isso, mesmo que o host e o cliente sejam no mesmo local.
Um sistema RMI é composto de várias partes:
É possível sugerir uma notação capaz de orientar melhor a escrita de código. Assim, no nosso exemplo, vamos ter:
Nome Exemplo Objectivo Sem sufixo Mensageiro.java Código do Interface Sufixo Impl MensageiroImpl.java Implementa os métodos (regras) Sufixo Server MensageiroServer.java Servidor: cria objectos Sufixo Client MensageiroClient.java Programa cliente
Sufixo _stub e skel
MensageiroImpl_Stub.class MensageiroImpl_Skel.class
Classes que mapeiam os métodos no cliente e no servidor
Um exemplo RMI
Vamos criar um sistema teste que implemente o RMI, utilizando um programa cliente e um programa servidor. Não vai ser utilizado um servidor FTP ou http e os programas estão alojados na mesma máquina com a mesma estrutura de directórios.
Os passos a serem seguidos agora são:
Antes de se criarem os Stub e Skeleton, a estrutura de ficheiros necessários terá a seguinte forma embora seja possível, mas não recomendável, juntar num único módulo o Interface e a sua implementação):
Crie agora um directório para guardar todos os ficheiros deste exemplo.
Interface
O primeiro passo, deverá ser então a criação da interface e compilá-la. A interface define todas as funcionalidades remotas oferecidas pelo serviço. Nomeie o ficheiro como Mensageiro.java.
import java.rmi.Remote;
import java.rmi.RemoteException;
javac MensageiroImpl.java
Observe que a classe utiliza (extende) a classe UnicastRemoteObject para linkar com o sistema RMI. Neste exemplo a classe extende a classe UnicastRemoteObject directamente. Quando uma classe extende a classe UnicastRemoteObject , ela deve disponibilizar um construtor que declare que ele pode lançar uma excepção RemoteException , pois quando o método super( ) é chamado, ele activa o código em UnicastRemoteObject , que executa o link RMI e a iniciação do objecto remoto.
Gerar os Stub e Skeleton
Gere os ficheiros Stub e Skeleton da classe de implementação que corre no servidor. Para isso execute o comando rmic , compilador RMI do JDK^1 (segundo o JRMP – Java Remote Method Protocol).
rmic MensageiroImpl
Existem contudo outras formas de gerar os stubs, dependendo da versão JAVA a utilizar:
Após a execução deste comando, você deverá ver no seu directório os ficheiros Mensageiro_Stub.class, Mensageiro_Skeleton.class. Todas as classes devem ser compiladas (com javac) antes da utilização do rmic.
Assim, após a geração de stubs, a estrutura típica de ficheiros de uma aplicação RMI ficará:
(^1) http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/rmic.html
Servidor
O serviço remoto RMI deve ser hospedado num processo servidor. A classe MensageiroServer é um servidor bem simples, que implementa somente os serviços pretendidos. Guarde o ficheiro como MensageiroServer.java.
import java.rmi.Naming; public class MensageiroServer {
public MensageiroServer() { try { Mensageiro m = new MensageiroImpl(); Naming.rebind("rmi://localhost:1099/MensageiroService", m); } catch( Exception e ) { System.out.println( "Trouble: " + e ); } }
public static void main(String[] args) { new MensageiroServer(); } }
Guarde este ficheiro (MensageiroServer.java) no seu directório e compile, com a seguinte linha de comando:
javac MensageiroServer.java
Cliente
O código fonte para o cliente é o seguinte. Guarde o ficheiro como MensageiroClient.java.
Naming.lookup(“rmi://host:port/name”);
Neste caso é possível indicar o IP da máquina e a porta disponibilizada para tal. No nosso exemplo poderia então ser, por exemplo:
Naming.lookup( "rmi://127.0.0.1:99/MensageiroService" );
Se pretender conhecer todos os servidores registados no registry , a classe Naming possui o método list , usado com a seguinte sintax:
String[] bindings = Naming.list(“
Guarde este ficheiro (MensageiroClient.java) no seu directório e compile, com a seguinte linha de comando:
javac MensageiroClient.java
Testar a aplicação RMI
Para testar um exemplo de RMI, talvez o melhor seja utilizar três consolas diferentes do MS- DOS.
Numa das consolas vai executar o programa servidor, numa outra execute o RMI Registry e na última execute o Cliente.
Inicie o RMI Registry. Você deve estar no mesmo directório em que estão gravados os ficheiros. Execute a seguinte linha de comando:
start rmiregistry
Aparecerá então uma consola DOS na qual está a ser executado o RMI registry.
Na segunda consola vamos executar o programa servidor. Você deve estar no mesmo directório em que estão gravados os ficheiros para executar o aplicativo. Execute o seguinte comando:
java MensageiroServer
Este comando inicia o servidor, carrega a sua implementação na memória e espera pela conexão com o cliente.
Na última consola, execute o programa cliente. Você deve estar no mesmo directório em que estão gravados os ficheiros. Para isso execute o seguinte comando:
java MensageiroClient
Se tudo correr bem, nas consolas 2 (servidor) e 3 (cliente) deverão ocorrer as seguintes mensagens.
Na consola 2 (servidor):
“Hellow World!”
Na consola 3 (cliente):
“This is not a Hello World! Message”
Tratamento de segurança
Tratando-se de um sistema que pretende aceder a processos que correm em máquinas diferentes, é importante considerar questões de permissões de acessos e outras, relacionadas com segurança.
Este processo, embora não muito simples, foca-se na análise das classes que gerem a segurança do JAVA, neste caso essencialmente a classe System.setSecurityManager. Para isto, o código no processo Cliente deverá conter a seguinte instrução
System.setSecurityManager(new RMISecurityManager());
Para que consiga ser executado, as condições de acesso e permissão poderão ser definidasem ficheiros externos (policy files) e referidos na altura da execução dos processos. O comando seguinte refere um ficheiro (policy.all) no qual estarão definindo todas as regras de
public static void main(String[] argv) { System.setSecurityManager(new RMISecurityManager()); try { myRMIImpl implementation = new myRMIImpl("myRMIImplInstance"); System.out.println("Servidor escuta..."); } catch (Exception e) { System.out.println("Exception occurred: " + e); } } }
Cliente import java.rmi.; import java.rmi.registry.; import java.rmi.server.*; import java.util.Date;
public class myRMIClient { public static void main(String[] argv) { System.setSecurityManager(new RMISecurityManager()); if (argv.length != 1) { System.out.println("usage: java myRMIClient
//invoke method on server object Date d = myServerObject.getDate(); System.out.println("Date on server is " + d); int x = myServerObject.sum(2,3); System.out.println("Soma de 2 com 3 = :" + x); } catch(Exception e) { System.out.println("Exception occured: " + e); System.exit(0); } System.out.println("RMI connection successful"); }
Repare-se que neste último caso a classe main() do Servidor está definida, não na classe que implementa o interface mas sim na classe instância.
Repare-se também que neste exemplo é possível indicar, na altura da execução do cliente, o IP da máquina onde está a executar o servidor.
Desenvolver aplicações RMI com Eclipse^2
Caso queiras utilizar o IDE Eclipse para escrever o código JAVA, segue um pequeno tutorial de como instalar o plugin necessário.
Configurar o JDK no Eclipse
a) Antes de tudo é fundamental configurar correctamente o JAVA no IDE Eclipse. Obviamente que terá de instalar uma das versões do JDK (JDK 1.4.2 ou JDK 1.5.0 ou
b) Supondo que optou pela instalação do JDK5.0, na pasta “C:\Program Files\Java\jdk1.5.0_09“. c) Inicie o Eclipse e aceda ao serviço Preferences (Window -> Preferences...) (Figura 1)
(^2) Capítulo criado com a colaboração do aluno Carlos Castro ( 3º ano de SIG) (^3) Não confunda JDK com JRE. Este último refere-se somente à máquina virtual
e) Se tiver de alterar a localização, por defeito, do JRE, seleccione o registo corrente (checkbox) e click em “Edit…”. (Figura 3)
Figura 3
f) Escreva o correspondente à versão que instalou ("jdk-1.5.0", por exemplo) no campo
correspondente ao local onde instalou o JDK, no campo "JRE home directory". Click em "OK" para terminar.
Nota:
Por vezes a portabilidade JAVA fica comprometida sempre que estejam várias versões JDK ou mesmo JRE instaladas. Isto pode acontecer, por exemplo, se compilar com uma versão (com javac ) e for executar (com java ) com outra versão distinta…para evitar isto, certifique-se que todas as variáveis de ambiente estão devidamente configuradas: PATH, CLASSPATH e JAVA_HOME.
Configuração do Plugin
Utilização
Desenvolver aplicações RMI sem IDE
Trata-se de desenvolver aplicações RMI sem a ajuda de qualquer IDE específico mas somente através de um editor de texto (situação comum para ambientes linux ou mesmo os menos adeptos ao Windows).
Neste caso, uma sugestão de organização de ficheiros e criação de scripts é apresentado nos seguintes tópicos:
Organização de ficheiros:
Uma estrutura indicada pode ser a apresentada na figura seguinte:
onde, na pastas:
endlocal
server.bat usada para iniciar o rmiregistry e a aplicação servidor
@rem executa o servidor. cd build\classes @rem inicia o rmiregistry start rmiregistry @rem corre o servidor start java -Djava.security.policy=policy.all MensageiroServer cd ....
client.bat usada para iniciar a aplicação cliente
@rem Run the SampleServer client cd build\classes java -Djava.security.policy=policy.all MensageiroClient cd ....
Conclusão
Se tudo correu bem, acabou de criar um sistema utilizando a tecnologia RMI. Apesar de ter executado os programas na mesma máquina, o RMI usa a pilha de rede TCP/IP para comunicar entre as três diferentes instâncias da JVM.
Resumindo, algumas das vantagens de um sistema RMI.
(^4) Mais informação em http://java.sun.com/javase/technologies/core/basic/rmi/whitepaper/index.jsp
Esta tecnologia compete directamente com a especificação CORBA e com a tecnologia Web Services.
Quiçá uma das desvantagens, entre outras, seja a dependência exclusiva do JAVA.
Luís Ferreira, Sandra Melo, Carlos Castro
Março, 2007