RMI permite que objetos Java se comuniquem através de uma rede, permitindo que métodos sejam chamados remotamente em outros computadores. Um exemplo é um sistema bancário onde terminais podem requisitar informações de clientes de um servidor central. RMI encapsula as requisições em objetos stub e skeleton para codificar e decodificar parâmetros e retornos entre cliente e servidor.
1. por Paulo César M. Jeveaux
Extraído do site : http://www.portaljava.com.br
RMI (Remote Method Invocation) é uma forma que Java adotou para trabalhar
com objetos Java/Java distribuídos. A idéia básica do RMI é obter um conjunto
de objetos colaboradores que se comuniquem através de uma rede.
Para entender as aplicações RMI, vamos analisar um problema: supondo a
existência de sistema bancário implementado em Java. Neste sistema, cada
terminal bancário pode requerer informações dos clientes do banco para um
centro de informações. Estas informações, uma vez obtidas, devem retornar ao
terminal. Sob o ponto de vista de programação, pode se pensar que o terminal
bancário é o cliente e o centro de informações é o servidor.
A implementação deste problema pode ser realizada de várias formas, tais
como:
* Abrir uma conexão através de sockets para o envio de dados puros;
* Utilizar JDBC caso o servidor tenha as informações implementadas em um
banco de dados relacional;
* Utilizar outras tecnologias como CORBA (Common Object Request Broker
Architecture), caso se esteja trabalhando com aplicativos Java/Java e
Java/outras linguagens como C++ e SmallTalk;
* Ou implementar o pedido e a resposta da informação como objetos. Neste
modelo, através de RMI, os objetos podem ser transportados entre o cliente e o
servidor.
Com RMI é possível transportar objetos pela rede e também chamar métodos
que estejam em outro computador, mantendo o objeto na máquina remota.
Supondo que o código do computador cliente invoca um método de um objeto
no servidor. Para um cliente invocar um método RMI, ele cria um objeto stub
que encapsula o pedido do cliente em um pacote de bytes composto por:
* Um identificador do objeto remoto a ser usado;
* Um número de operação para descrever o método a ser invocado;
* Um conjunto de parâmetros codificados (marshalling – processo de
codificação dos parâmetros para um formato apropriado para o transporte de
rede).
2. Para o servidor receber a informação que está no stub, ele cria um objeto
skeleton. O skeleton executa as seguintes ações:
* Decodifica os parâmetros;
* Chama o método desejado;
* Captura o valor de retorno ou exceção e codifica (marshalling);
* Retorna o valor codificado para o cliente.
O stub decodifica o valor de retorno do servidor, que pode ser uma exceção,
mas que em geral é o retorno da chamada do método remoto.
Deve-se ter um cuidado especial no momento em que não estão mais sendo
utilizados os objetos remotos. Isto porque o Garbage Collection não pode
detectar ligações de objetos remotos não referenciados. Desta forma as
ligações devem ser explicitamente quebradas pelo programador.
Sempre que é evocado um método remoto, as classes stub e skeleton serão
carregadas com um gerenciador de segurança, que determina o que uma
classe pode fazer. Semelhante aos gerenciadores de segurança dos browsers.
O gerenciador de segurança é definido pelo programador, no momento da
implementação do programa. Java já dispõe de gerenciadores de segurança
bastante eficazes, porém, o programador pode criar novos gerenciadores, caso
ache necessário.
Para realizar uma operação RMI, é preciso criar, tanto do lado do cliente,
quanto do lado do servidor, uma interface para o objeto que será referenciado.
Isto porque o cliente, embora não tenha o objeto real, que está no servidor,
deve saber as ações que pode executar sobre este objeto (o protocolo).
3. Primeiro Programa RMI
O primeiro arquivo a analisar é a interface apresentada no arquivo Hello.java.
Esta interface informa a existência de um único método: sayHello(), este
método tem a função de retornar uma String para um objeto remoto.
Todas as interfaces RMI, devem ser derivadas da classe java.rmi.Remote e
devem ter o tratamento de suas exceções realizadas através da
java.rmi.RemoteException, para que as exceções sejam repassadas
remotamente.
public interface Hello extends java.rmi.Remote {
String sayHello() throws java.rmi.RemoteException;
}
O arquivo HelloImpl.java contém a classe HelloImpl, que implementa a
interface Hello no servidor.
HelloImpl é uma subclasse da classe UnicastRemoteObject que é derivada da
classe RemoteServer. A RemoteServer é uma classe abstrata, utilizada para a
implementação de RMI pela linguagem Java. Esta classe inicia uma thread,
que metem o objeto HelloImpl ativo, a fim de que clientes possam se conectar
ao programa.
import java.rmi.*;
import java.rmi.server.UnicastRemoteServer;
public class HelloImpl extends UnicastRemoteServer implements Hello {
private String nome;
public HelloImpl(String s) throws java.rmi.RemoteException {
super();
nome = s;
}
public String sayHello() throws RemoteException {
return “Hello World !!!”;
}
4. public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try {
HelloImpl obj = new HelloImpl(“HelloServer”);
Naming.rebind(“HelloServer”, obj);
System.out.println(“HelloImpl foi criado e registrado”);
}
catch(Exception e) {
System.out.println(“Ocorreu uma exceção no servidor”);
e.printStacktrace();
}
}
}
Ao ser criada a classe HelloImpl, o gerenciador de segurança RMI
(RMISecurityManager) é criado e instalado através do código:
System.setSecurityManager(new RMISecurityManager());
O objeto obj, passa a ser construído, com o construtor da classe, e cadastrado
no sistema operacional, através do método rebind(String str, Remote r) da
classe Naming. A classe Naming fornece um mecanismo para obter referencias
a objetos remotos baseados na sintaxe da URL. Onde uma URL para objetos
remotos é usualmente especificada pelo Host, porta e nome:
rmi://host:porta/nome.
Naming.rebind(“HelloServer”, obj);
5. O cliente RMI está implementado através de um applet, na classe HelloApplet.
import java.awt.*;
import java.rmi.*;
public class HelloApplet extends java.Applet.Applet {
String mensagem = “”;
Public void init() {
try {
Hello obj = (Hello)Naming.lookup(“//”+getCodeBase().getHost()
+ “/HelloServer”);
mensagem = obj.sayHello();
}
catch(Exception e) {
System.out.println(“Ocorreu uma exceção”);
e.printStackTrace();
}
}
public void paint(Graphics g) {
g.drawString(mensagem, 25, 50);
}
}
6. O applet, ao ser inicializado, chama o método init(). Este por sua vez cria um
objeto Hello, a partir de um cadastro em uma máquina Remota (servidor). Para
tanto, fornece a URL deste objeto para o método lookup(String url). Como este
método retorna genericamente um objeto do tipo Remote, deve ser colocado
um cast explícito para o objeto que está sendo criado, no caso (Hello).
Hello obj = (Hello)Naming.lookup(“//”+getCodeBase().getHost() +
“/HelloServer”);
Através da interface, a classe cliente pode ter conhecimento dos métodos que
pode evocar remotamente. Neste caso apenas o método abaixo:
mensagem = obj.sayHello();
A mensagem será exibida através do método drawString(String s, int x, int y),
sempre que o browser chamar o método paint(Graphics g).
Para executar o programa, foi criado um arquivo de batch chamado de Run.bat.
Este arquivo contém as seguintes linhas:
javac *.java
start /min rmiregistry
rmic HelloImpl
start java HelloImpl
pause
appletviewer cliente.html
A instrução javac *.java força a compilação de todos os arquivos .java para
gerar os arquivos .class.
A instrução start /min rmiregistry, serve para ativar o serviço de registros de
S.O. para que a classe possa ser registrada no servidor.
A instrução rmic HelloImpl cria automaticamente as classes necessárias para
gerar os objetos stub e skeleton. Neste caso em específico serão geradas as
classes: HelloImpl_Stub.class e HelloImpl_Skel.class.
A instrução start java HelloImpl inicia o servidor em um processo separado.
Para terminar o processo basta pressionar CTRL-C.
A instrução appletviewer cliente.html inicia o cliente através da chamada de
uma página HTML eu contém o applet descrito acima. Este applet, por sua vez,
chamará o método remoto.
7. IMPORTANTE: Para trabalhar com RMI, mesmo em um único computador, é
necessário que o computador tenha disponível os serviços de rede TCP/IP.
Leia mais em: Tutorial RMI - Invocação remota de métodos
http://www.devmedia.com.br/tutorial-rmi-invocacao-remota-de-
metodos/4493#ixzz1wMhrsEP8